diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2ffe6c4da9..0815906c23 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,7 +8,7 @@ - [ ] Add JavaDocs and other comments explaining the behavior. - [ ] When adding or updating methods that fetch entities, add `@link` JavaDoc entries to the relevant documentation on https://docs.github.com/en/rest . - [ ] Add tests that cover any added or changed code. This generally requires capturing snapshot test data. See [CONTRIBUTING.md](CONTRIBUTING.md) for details. -- [ ] Run `mvn -D enable-ci clean install site "-Dsurefire.argLine=--add-opens java.base/java.net=ALL-UNNAMED"` locally. If this command doesn't succeed, your change will not pass CI. +- [ ] Run `mvn -D enable-ci clean install site` locally. If this command doesn't succeed, your change will not pass CI. - [ ] Push your changes to a branch other than `main`. You will create your PR from that branch. # When creating a PR: diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index 33f089f717..e37c504641 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -60,25 +60,6 @@ jobs: # running install site seems to more closely imitate real site deployment, # more likely to prevent failed deployment run: mvn -B clean install site -DskipTests --file pom.xml - test-bridged: - name: build-and-test Bridged (Java 17) - # Does not require build output, but orders execution to prevent launching test workflows when simple build fails - needs: build - runs-on: ubuntu-latest - strategy: - fail-fast: true - steps: - - uses: actions/checkout@v4 - - name: Set up JDK - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: 'temurin' - cache: 'maven' - - name: Maven Install (skipTests) - env: - MAVEN_OPTS: ${{ env.JAVA_11_PLUS_MAVEN_OPTS }} - run: mvn -B clean install -Pbridged -D enable-ci --file pom.xml "-Dsurefire.argLine=--add-opens java.base/java.net=ALL-UNNAMED" test: name: test (${{ matrix.os }}, Java ${{ matrix.java }}) # Does not require build output, but orders execution to prevent launching test workflows when simple build fails @@ -126,7 +107,7 @@ jobs: name: maven-test-target-directory path: target - name: Codecov Report - uses: codecov/codecov-action@v5.4.0 + uses: codecov/codecov-action@v4.5.0 with: # Codecov token from https://app.codecov.io/gh/hub4j/github-api/settings token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/publish_release_branch.yml b/.github/workflows/publish_release_branch.yml index 72e5c21a0f..6e3041a436 100644 --- a/.github/workflows/publish_release_branch.yml +++ b/.github/workflows/publish_release_branch.yml @@ -56,14 +56,6 @@ jobs: MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN_PASSWORD }} MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSPHRASE }} - - name: Publish package with bridge methods - run: mvn -B clean deploy -DskipTests -Prelease -Pbridged - env: - MAVEN_OPTS: ${{ env.JAVA_11_PLUS_MAVEN_OPTS }} - MAVEN_USERNAME: ${{ secrets.OSSRH_TOKEN_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN_PASSWORD }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSPHRASE }} - publish_gh_pages: runs-on: ubuntu-latest needs: build diff --git a/.gitignore b/.gitignore index 5a585eb651..543ce576cd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,6 @@ target .classpath .project .settings/ -.metadata/ .DS_Store dependency-reduced-pom.xml diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..4d245050fa --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip diff --git a/README.md b/README.md index db22e163bb..76474f45b4 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,4 @@ [![codecov](https://codecov.io/gh/hub4j/github-api/branch/main/graph/badge.svg?token=j1jQqydZLJ)](https://codecov.io/gh/hub4j/github-api) -See https://hub4j.github.io/github-api/ for more details +See https://github-api.kohsuke.org/ for more details diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000000..acec2caec5 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,4 @@ +jdk: + - openjdk17 +maven: + version: 3.8.6 \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100755 index 0000000000..19529ddf8c --- /dev/null +++ b/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000000..b150b91ed5 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/pom.xml b/pom.xml index 70697ec5f2..4f41a952f7 100644 --- a/pom.xml +++ b/pom.xml @@ -1,60 +1,29 @@ - 4.0.0 org.kohsuke - ${github-api.artifactId} - 2.0-rc.4-SNAPSHOT + github-api + 2.0-rc.4-patched-SNAPSHOT GitHub API for Java + https://github-api.kohsuke.org/ GitHub API for Java - https://hub4j.github.io/github-api/ - - - - The MIT license - https://www.opensource.org/licenses/mit-license.php - repo - - - - - - kohsuke - Kohsuke Kawaguchi - kk@kohsuke.org - - - bitwiseman - Liam Newman - bitwiseman@gmail.com - - - - - - User List - github-api@googlegroups.com - https://groups.google.com/forum/#!forum/github-api - - scm:git:git@github.com/hub4j/${project.artifactId}.git scm:git:ssh://git@github.com/hub4j/${project.artifactId}.git - HEAD https://github.com/hub4j/github-api/ + HEAD - - sonatype-nexus-staging - Nexus Release Repository - ${nexus.serverUrl}/service/local/staging/deploy/maven2/ - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - ${nexus.serverUrl}/content/repositories/snapshots/ + github + https://maven.pkg.github.com/FelixTJDietrich/github-api + + github + GitHub FelixTJDietrich Apache Maven Packages + https://maven.pkg.github.com/FelixTJDietrich/github-api + github-pages gitsite:git@github.com/hub4j/${project.artifactId}.git @@ -62,241 +31,38 @@ - github-api + 3.3.4 + UTF-8 + 4.8.6.4 + 4.8.6 + true 3.0 + 4.12.0 + 3.9.1 0.70 0.50 false - - 0.12.6 - - https://oss.sonatype.org - 4.12.0 - 3.10.2 - UTF-8 - true - 4.9.3.0 - 4.8.6 - 3.3.5 - - - - - - - com.fasterxml.jackson - jackson-bom - 2.18.3 - pom - import - - - org.junit - junit-bom - 5.12.1 - pom - import - - - org.slf4j - slf4j-bom - 2.0.17 - pom - import - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - junit - junit - 4.13.2 - - - org.hamcrest - hamcrest - ${hamcrest.version} - - - org.hamcrest - hamcrest-core - ${hamcrest.version} - - - org.hamcrest - hamcrest-library - ${hamcrest.version} - - - - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - - - com.infradna.tool - bridge-method-annotation - 1.30 - true - - - com.squareup.okhttp3 - okhttp - ${okhttp3.version} - true - - - com.squareup.okio - okio - ${okio.version} - true - - - commons-io - commons-io - 2.16.1 - - - io.jsonwebtoken - jjwt-api - ${jjwt.suite.version} - true - - - io.jsonwebtoken - jjwt-impl - ${jjwt.suite.version} - true - - - io.jsonwebtoken - jjwt-jackson - ${jjwt.suite.version} - true - - - org.apache.commons - commons-lang3 - 3.17.0 - - - com.github.spotbugs - spotbugs-annotations - ${spotbugs.version} - provided - - - com.github.npathai - hamcrest-optional - 2.0.0 - test - - - com.github.tomakehurst - wiremock-jre8-standalone - 2.35.2 - test - - - com.google.code.gson - gson - 2.12.1 - test - - - com.google.guava - guava - 33.4.6-jre - test - - - com.tngtech.archunit - archunit - 1.4.0 - test - - - junit - junit - test - - - org.awaitility - awaitility - 4.3.0 - test - - - org.hamcrest - hamcrest - test - - - - org.hamcrest - hamcrest-core - test - - - org.hamcrest - hamcrest-library - test - - - - org.junit.vintage - junit-vintage-engine - test - - - org.kohsuke - wordnet-random-name - 1.6 - test - - - org.mockito - mockito-core - 5.16.1 - test - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - - - - repo.jenkins-ci.org - https://repo.jenkins-ci.org/public/ - - + + + + + + org.apache.maven.scm + maven-scm-provider-gitexe + 2.1.0 + + + org.apache.maven.scm + maven-scm-manager-plexus + 2.1.0 + + src/test/resources @@ -308,58 +74,32 @@ - com.infradna.tool - bridge-method-injector - 1.30 - - - - process - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.2.7 + org.codehaus.mojo + versions-maven-plugin + 2.17.1 org.apache.maven.plugins maven-help-plugin - 3.5.1 + 3.5.0 - org.apache.maven.plugins - maven-javadoc-plugin - 3.11.2 + maven-surefire-plugin + 3.5.0 - 11 - 11 - true - all + + false - maven-resources-plugin - 3.3.1 - - + org.apache.maven.plugins maven-source-plugin 3.3.1 - maven-surefire-plugin - 3.5.3 - - - false - - - - org.codehaus.mojo - versions-maven-plugin - 2.18.0 + org.apache.maven.plugins + maven-gpg-plugin + 3.2.7 org.jacoco @@ -389,10 +129,10 @@ check + verify check - verify ${project.build.directory}/jacoco-it.exec @@ -458,6 +198,17 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + 3.10.0 + + 11 + 11 + true + all + + org.sonatype.plugins nexus-staging-maven-plugin @@ -465,129 +216,66 @@ true sonatype-nexus-staging - ${nexus.serverUrl}/ + https://oss.sonatype.org/ true - - com.diffplug.spotless - spotless-maven-plugin - 2.44.3 - - - - src/main/java/**/*.java - src/test/java/**/*.java - - - - 4.35 - ${basedir}/src/build/eclipse/formatter.xml - true - true - false - - - - ${basedir}/src/build/eclipse/eclipse.importorder - - - - - - - - - - + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} - spotless-check - + process-test-aot - - check + process-test-aot - com.github.ekryd.sortpom - sortpom-maven-plugin - 4.0.0 - - false - scope,groupId,artifactId - groupId,artifactId - true - ${sortpom.verifyFail} - - - - - verify - - validate - - + org.apache.maven.plugins + maven-site-plugin + 3.20.0 - com.github.siom79.japicmp - japicmp-maven-plugin - 0.23.1 + org.apache.maven.plugins + maven-release-plugin + 3.1.1 - - true - - true - true - - - org.kohsuke.github.internal - - + true + false + release + deploy - - - - cmp - - verify - - - com.github.spotbugs - spotbugs-maven-plugin - ${spotbugs-maven-plugin.version} - - true - ${spotbugs-maven-plugin.failOnError} - + org.sonatype.plugins + nexus-staging-maven-plugin + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 3.7.0 - - com.github.spotbugs - spotbugs - ${spotbugs.version} + org.apache.bcel + bcel + 6.10.0 - - - run-spotbugs - - check - - verify - - maven-compiler-plugin - 3.14.0 + 3.13.0 11 11 @@ -596,11 +284,25 @@ org.jenkins-ci annotation-indexer - 1.18 + 1.17 + + maven-surefire-plugin + + @{jacoco.surefire.argLine} ${surefire.argLine} + + + + default-test + + src/test/resources/slow-or-flaky-tests.txt + + + + org.apache.maven.plugins maven-jar-plugin @@ -614,110 +316,281 @@ - org.apache.maven.plugins - maven-project-info-reports-plugin - 3.9.0 - - - org.apache.bcel - bcel - 6.10.0 - - - - - org.apache.maven.plugins - maven-release-plugin - 3.1.1 + com.diffplug.spotless + spotless-maven-plugin + 2.43.0 + + + spotless-check + + + + check + + + - true - false - release - deploy + + + src/main/java/**/*.java + src/test/java/**/*.java + + + + ${basedir}/src/build/eclipse/formatter.xml + + + + ${basedir}/src/build/eclipse/eclipse.importorder + + + + + + + - org.apache.maven.plugins - maven-site-plugin - 3.21.0 - - - maven-surefire-plugin + com.github.spotbugs + spotbugs-maven-plugin + ${spotbugs-maven-plugin.version} - @{jacoco.surefire.argLine} ${surefire.argLine} - - ${project.artifactId} - + true + ${spotbugs-maven-plugin.failOnError} - default-test - - src/test/resources/slow-or-flaky-tests.txt - + run-spotbugs + verify + + check + + + + + com.github.spotbugs + spotbugs + ${spotbugs.version} + + - org.sonatype.plugins - nexus-staging-maven-plugin - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} + com.github.siom79.japicmp + japicmp-maven-plugin + 0.23.0 + + + + ${project.groupId} + ${project.artifactId} + 2.0.0-alpha-1 + jar + + + + true --> + + true + true + + + org.kohsuke.github.internal + + + - process-test-aot + verify - process-test-aot + cmp - - - org.apache.maven.scm - maven-scm-provider-gitexe - 2.1.0 - - - org.apache.maven.scm - maven-scm-manager-plexus - 2.1.0 - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-project-info-reports-plugin - - - org.jacoco - jacoco-maven-plugin - - - - - report-integration - - - - - - + + + + + com.fasterxml.jackson + jackson-bom + 2.18.0 + import + pom + + + + + + + org.apache.commons + commons-lang3 + 3.17.0 + + + com.tngtech.archunit + archunit + 1.3.0 + test + + + org.hamcrest + hamcrest + ${hamcrest.version} + test + + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + test + + + + org.hamcrest + hamcrest-core + ${hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${hamcrest.version} + test + + + com.github.npathai + hamcrest-optional + 2.0.0 + test + + + junit + junit + 4.13.2 + test + + + org.awaitility + awaitility + 4.2.2 + test + + + + org.junit.vintage + junit-vintage-engine + 5.10.2 + test + + + com.fasterxml.jackson.core + jackson-databind + + + commons-io + commons-io + 2.16.1 + + + com.infradna.tool + bridge-method-annotation + 1.30 + true + + + com.google.guava + guava + 33.3.1-jre + test + + + io.jsonwebtoken + jjwt-api + ${jjwt.suite.version} + true + + + io.jsonwebtoken + jjwt-impl + ${jjwt.suite.version} + true + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.suite.version} + true + + + com.squareup.okio + okio + ${okio.version} + true + + + com.squareup.okhttp3 + okhttp + ${okhttp3.version} + true + + + org.kohsuke + wordnet-random-name + 1.6 + test + + + org.mockito + mockito-core + 5.14.0 + test + + + com.github.spotbugs + spotbugs-annotations + ${spotbugs.version} + provided + + + com.github.tomakehurst + wiremock-jre8-standalone + 2.35.2 + test + + + com.google.code.gson + gson + 2.11.0 + test + + + org.slf4j + slf4j-simple + 2.0.16 + test + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + + + + repo.jenkins-ci.org + https://repo.jenkins-ci.org/public/ + + @@ -734,10 +607,10 @@ okhttp-test + integration-test test - integration-test ${project.basedir}/target/${project.artifactId}-${project.version}.jar src/test/resources/slow-or-flaky-tests.txt @@ -745,11 +618,11 @@ - httpclient-test-tracing + httpclient-test + integration-test test - integration-test ${project.basedir}/target/${project.artifactId}-${project.version}.jar false @@ -763,10 +636,10 @@ slow-or-flaky-test + integration-test test - integration-test ${project.basedir}/target/${project.artifactId}-${project.version}.jar 2 @@ -775,10 +648,10 @@ slow-or-flaky-test-tracing + integration-test test - integration-test ${project.basedir}/target/${project.artifactId}-${project.version}.jar 2 @@ -792,10 +665,10 @@ jwt0.11.x-test + integration-test test - integration-test ${project.basedir}/target/${project.artifactId}-${project.version}.jar false @@ -828,56 +701,19 @@ - - bridged - - - github-api-bridged - - - - - com.infradna.tool - bridge-method-injector - - - maven-resources-plugin - - - copy-bridged-resources - - copy-resources - - - validate - - ${basedir}/target/classes/META-INF/native-image/org.kohsuke/${github-api.artifactId} - - - src/main/resources/META-INF/native-image/org.kohsuke/github-api - - - - - - - - - ci-non-windows - - !windows - enable-ci + + !windows + true - stop @@ -889,17 +725,21 @@ + + org.jacoco + jacoco-maven-plugin + com.diffplug.spotless spotless-maven-plugin spotless-check + + process-sources check - - process-sources @@ -910,10 +750,10 @@ enforce-jacoco-exist + verify enforce - verify @@ -927,10 +767,6 @@ - - org.jacoco - jacoco-maven-plugin - @@ -938,16 +774,20 @@ release + + org.jacoco + jacoco-maven-plugin + org.apache.maven.plugins maven-gpg-plugin sign-artifacts + verify sign - verify --pinentry-mode @@ -959,35 +799,79 @@ org.apache.maven.plugins - maven-javadoc-plugin + maven-source-plugin - attach-javadocs + attach-sources - jar + jar-no-fork org.apache.maven.plugins - maven-source-plugin + maven-javadoc-plugin - attach-sources + attach-javadocs - jar-no-fork + jar - - org.jacoco - jacoco-maven-plugin - + + + + org.jacoco + jacoco-maven-plugin + + + + + report-integration + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.apache.maven.plugins + maven-project-info-reports-plugin + + + + + + + The MIT license + https://www.opensource.org/licenses/mit-license.php + repo + + + + + + User List + github-api@googlegroups.com + https://groups.google.com/forum/#!forum/github-api + + + + + + Kohsuke Kawaguchi + kohsuke + kk@kohsuke.org + + diff --git a/src/main/java/org/kohsuke/github/AbstractBuilder.java b/src/main/java/org/kohsuke/github/AbstractBuilder.java index af78f8b47a..8a581270e6 100644 --- a/src/main/java/org/kohsuke/github/AbstractBuilder.java +++ b/src/main/java/org/kohsuke/github/AbstractBuilder.java @@ -27,29 +27,29 @@ * set().otherName(value); * *

- * If {@code S} is the same as {@code R}, {@link #with(String, Object)} will commit changes after the first value change - * and return a {@code R} from {@link #done()}. + * If {@link S} is the same as {@link R}, {@link #with(String, Object)} will commit changes after the first value change + * and return a {@link R} from {@link #done()}. *

*

- * If {@code S} is not the same as {@code R}, {@link #with(String, Object)} will batch together multiple changes and let + * If {@link S} is not the same as {@link R}, {@link #with(String, Object)} will batch together multiple changes and let * the user call {@link #done()} when they are ready. * * @author Liam Newman * @param * Final return type built by this builder returned when {@link #done()}} is called. * @param - * Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If {@code S} - * the same as {@code R}, this builder will commit changes after each call to {@link #with(String, Object)}. + * Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If {@link S} + * the same as {@link R}, this builder will commit changes after each call to {@link #with(String, Object)}. */ abstract class AbstractBuilder extends GitHubInteractiveObject implements GitHubRequestBuilderDone { - @CheckForNull - private final R baseInstance; + @Nonnull + private final Class returnType; private final boolean commitChangesImmediately; - @Nonnull - private final Class returnType; + @CheckForNull + private final R baseInstance; /** The requester. */ @Nonnull @@ -68,7 +68,7 @@ abstract class AbstractBuilder extends GitHubInteractiveObject implements * @param finalReturnType * the final return type for built by this builder returned when {@link #done()}} is called. * @param intermediateReturnType - * the intermediate return type of type {@code S} returned by calls to {@link #with(String, Object)}. + * the intermediate return type of type {@link S} returned by calls to {@link #with(String, Object)}. * Must either be equal to {@code builtReturnType} or this instance must be castable to this class. If * not, the constructor will throw {@link IllegalArgumentException}. * @param root @@ -111,54 +111,54 @@ public R done() throws IOException { } /** - * Chooses whether to return a continuing builder or an updated data record + * Applies a value to a name for this builder. * - * If {@code S} is the same as {@code R}, this method will commit changes after the first value change and return a - * {@code R} from {@link #done()}. + * If {@link S} is the same as {@link R}, this method will commit changes after the first value change and return a + * {@link R} from {@link #done()}. * - * If {@code S} is not the same as {@code R}, this method will return an {@code S} and letting the caller batch + * If {@link S} is not the same as {@link R}, this method will return an {@link S} and letting the caller batch * together multiple changes and call {@link #done()} when they are ready. * + * @param name + * the name of the field + * @param value + * the value of the field * @return either a continuing builder or an updated data record * @throws IOException * if an I/O error occurs */ @Nonnull @BetaApi - protected S continueOrDone() throws IOException { - // This little bit of roughness in this base class means all inheriting builders get to create Updater and - // Setter classes from almost identical code. Creator can often be implemented with significant code reuse as - // well. - if (commitChangesImmediately) { - // These casts look strange and risky, but they they're actually guaranteed safe due to the return path - // being based on the previous comparison of class instances passed to the constructor. - return (S) done(); - } else { - return (S) this; - } + protected S with(@Nonnull String name, Object value) throws IOException { + requester.with(name, value); + return continueOrDone(); } /** - * Applies a value to a name for this builder. + * Chooses whether to return a continuing builder or an updated data record * - * If {@code S} is the same as {@code R}, this method will commit changes after the first value change and return a - * {@code R} from {@link #done()}. + * If {@link S} is the same as {@link R}, this method will commit changes after the first value change and return a + * {@link R} from {@link #done()}. * - * If {@code S} is not the same as {@code R}, this method will return an {@code S} and letting the caller batch + * If {@link S} is not the same as {@link R}, this method will return an {@link S} and letting the caller batch * together multiple changes and call {@link #done()} when they are ready. * - * @param name - * the name of the field - * @param value - * the value of the field * @return either a continuing builder or an updated data record * @throws IOException * if an I/O error occurs */ @Nonnull @BetaApi - protected S with(@Nonnull String name, Object value) throws IOException { - requester.with(name, value); - return continueOrDone(); + protected S continueOrDone() throws IOException { + // This little bit of roughness in this base class means all inheriting builders get to create Updater and + // Setter classes from almost identical code. Creator can often be implemented with significant code reuse as + // well. + if (commitChangesImmediately) { + // These casts look strange and risky, but they they're actually guaranteed safe due to the return path + // being based on the previous comparison of class instances passed to the constructor. + return (S) done(); + } else { + return (S) this; + } } } diff --git a/src/main/java/org/kohsuke/github/EnterpriseManagedSupport.java b/src/main/java/org/kohsuke/github/EnterpriseManagedSupport.java index 9d3030558d..5b4c62be6b 100644 --- a/src/main/java/org/kohsuke/github/EnterpriseManagedSupport.java +++ b/src/main/java/org/kohsuke/github/EnterpriseManagedSupport.java @@ -14,22 +14,11 @@ */ class EnterpriseManagedSupport { - private static final Logger LOGGER = Logger.getLogger(EnterpriseManagedSupport.class.getName()); static final String COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS = "Could not retrieve organization external groups"; static final String NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR = "This organization is not part of externally managed enterprise."; - static final String TEAM_CANNOT_BE_EXTERNALLY_MANAGED_ERROR = "This team cannot be externally managed since it has explicit members."; - private static String logUnexpectedFailure(final JsonProcessingException exception, final String payload) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw); - exception.printStackTrace(pw); - return String.format("Could not parse GitHub error response: '%s'. Full stacktrace follows:%n%s", payload, sw); - } - - static EnterpriseManagedSupport forOrganization(final GHOrganization org) { - return new EnterpriseManagedSupport(org); - } + private static final Logger LOGGER = Logger.getLogger(EnterpriseManagedSupport.class.getName()); private final GHOrganization organization; @@ -37,15 +26,6 @@ private EnterpriseManagedSupport(GHOrganization organization) { this.organization = organization; } - Optional filterException(final GHException e) { - if (e.getCause() instanceof HttpException) { - final HttpException he = (HttpException) e.getCause(); - return filterException(he, COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS) - .map(translated -> new GHException(COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS, translated)); - } - return Optional.empty(); - } - Optional filterException(final HttpException he, final String scenario) { if (he.getResponseCode() == 400) { final String responseMessage = he.getMessage(); @@ -66,4 +46,24 @@ Optional filterException(final HttpException he, final String sce return Optional.empty(); } + Optional filterException(final GHException e) { + if (e.getCause() instanceof HttpException) { + final HttpException he = (HttpException) e.getCause(); + return filterException(he, COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS) + .map(translated -> new GHException(COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS, translated)); + } + return Optional.empty(); + } + + static EnterpriseManagedSupport forOrganization(final GHOrganization org) { + return new EnterpriseManagedSupport(org); + } + + private static String logUnexpectedFailure(final JsonProcessingException exception, final String payload) { + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); + exception.printStackTrace(pw); + return String.format("Could not parse GitHub error response: '%s'. Full stacktrace follows:%n%s", payload, sw); + } + } diff --git a/src/main/java/org/kohsuke/github/GHApp.java b/src/main/java/org/kohsuke/github/GHApp.java index 628ac0cf01..fd1db5c609 100644 --- a/src/main/java/org/kohsuke/github/GHApp.java +++ b/src/main/java/org/kohsuke/github/GHApp.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Collections; import java.util.Date; import java.util.List; @@ -21,20 +20,48 @@ */ public class GHApp extends GHObject { - private String description; + /** + * Create default GHApp instance + */ + public GHApp() { + } - private List events; - private String externalUrl; - private String htmlUrl; - private long installationsCount; - private String name; private GHUser owner; - private Map permissions; + private String name; private String slug; + private String description; + private String externalUrl; + private Map permissions; + private List events; + private long installationsCount; + private String htmlUrl; + /** - * Create default GHApp instance + * Gets owner. + * + * @return the owner */ - public GHApp() { + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getOwner() { + return owner; + } + + /** + * Gets name. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Gets the slug name of the GitHub app. + * + * @return the slug name of the GitHub app + */ + public String getSlug() { + return slug; } /** @@ -46,6 +73,15 @@ public String getDescription() { return description; } + /** + * Gets external url. + * + * @return the external url + */ + public String getExternalUrl() { + return externalUrl; + } + /** * Gets events. * @@ -58,12 +94,12 @@ public List getEvents() { } /** - * Gets external url. + * Gets installations count. * - * @return the external url + * @return the installations count */ - public String getExternalUrl() { - return externalUrl; + public long getInstallationsCount() { + return installationsCount; } /** @@ -75,6 +111,45 @@ public URL getHtmlUrl() { return GitHubClient.parseURL(htmlUrl); } + /** + * Gets permissions. + * + * @return the permissions + */ + public Map getPermissions() { + return Collections.unmodifiableMap(permissions); + } + + /** + * Obtains all the installations associated with this app. + *

+ * You must use a JWT to access this endpoint. + * + * @return a list of App installations + * @see List installations + */ + public PagedIterable listInstallations() { + return listInstallations(null); + } + + /** + * Obtains all the installations associated with this app since a given date. + *

+ * You must use a JWT to access this endpoint. + * + * @param since + * - Allows users to get installations that have been updated since a given date. + * @return a list of App installations since a given time. + * @see List installations + */ + public PagedIterable listInstallations(final Date since) { + Requester requester = root().createRequest().withUrlPath("/app/installations"); + if (since != null) { + requester.with("since", GitHubClient.printDate(since)); + } + return requester.toIterable(GHAppInstallation[].class, null); + } + /** * Obtain an installation associated with this app. *

@@ -151,112 +226,4 @@ public GHAppInstallation getInstallationByUser(String name) throws IOException { .fetch(GHAppInstallation.class); } - /** - * Gets installations count. - * - * @return the installations count - */ - public long getInstallationsCount() { - return installationsCount; - } - - /** - * Gets name. - * - * @return the name - */ - public String getName() { - return name; - } - - /** - * Gets owner. - * - * @return the owner - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getOwner() { - return owner; - } - - /** - * Gets permissions. - * - * @return the permissions - */ - public Map getPermissions() { - return Collections.unmodifiableMap(permissions); - } - - /** - * Gets the slug name of the GitHub app. - * - * @return the slug name of the GitHub app - */ - public String getSlug() { - return slug; - } - - /** - * Obtains all the installation requests associated with this app. - *

- * You must use a JWT to access this endpoint. - * - * @return a list of App installation requests - * @see List - * installation requests - */ - public PagedIterable listInstallationRequests() { - return root().createRequest() - .withUrlPath("/app/installation-requests") - .toIterable(GHAppInstallationRequest[].class, null); - } - - /** - * Obtains all the installations associated with this app. - *

- * You must use a JWT to access this endpoint. - * - * @return a list of App installations - * @see List installations - */ - public PagedIterable listInstallations() { - return listInstallations(GitHubClient.toInstantOrNull(null)); - } - - /** - * Obtains all the installations associated with this app since a given date. - *

- * You must use a JWT to access this endpoint. - * - * @param since - * - Allows users to get installations that have been updated since a given date. - * @return a list of App installations since a given time. - * @see List installations - * @deprecated use {@link #listInstallations(Instant)} - */ - @Deprecated - public PagedIterable listInstallations(final Date since) { - return listInstallations(since.toInstant()); - } - - /** - * Obtains all the installations associated with this app since a given date. - *

- * You must use a JWT to access this endpoint. - * - * @param since - * - Allows users to get installations that have been updated since a given date. - * @return a list of App installations since a given time. - * @see List installations - */ - public PagedIterable listInstallations(final Instant since) { - Requester requester = root().createRequest().withUrlPath("/app/installations"); - if (since != null) { - requester.with("since", GitHubClient.printInstant(since)); - } - return requester.toIterable(GHAppInstallation[].class, null); - } - } diff --git a/src/main/java/org/kohsuke/github/GHAppCreateTokenBuilder.java b/src/main/java/org/kohsuke/github/GHAppCreateTokenBuilder.java index 54c5228257..edab276e90 100644 --- a/src/main/java/org/kohsuke/github/GHAppCreateTokenBuilder.java +++ b/src/main/java/org/kohsuke/github/GHAppCreateTokenBuilder.java @@ -14,9 +14,9 @@ */ public class GHAppCreateTokenBuilder extends GitHubInteractiveObject { - private final String apiUrlTail; /** The builder. */ protected final Requester builder; + private final String apiUrlTail; /** * Instantiates a new GH app create token builder. @@ -34,33 +34,17 @@ public class GHAppCreateTokenBuilder extends GitHubInteractiveObject { } /** - * Creates an app token with all the parameters. - *

- * You must use a JWT to access this endpoint. - * - * @return a GHAppInstallationToken - * @throws IOException - * on error - */ - public GHAppInstallationToken create() throws IOException { - return builder.method("POST").withUrlPath(apiUrlTail).fetch(GHAppInstallationToken.class); - } - - /** - * Set the permissions granted to the access token. The permissions object includes the permission names and their - * access type. + * By default the installation token has access to all repositories that the installation can access. To restrict + * the access to specific repositories, you can provide the repository_ids when creating the token. When you omit + * repository_ids, the response does not contain neither the repositories nor the permissions key. * - * @param permissions - * Map containing the permission names and types. + * @param repositoryIds + * Array containing the repositories Ids * @return a GHAppCreateTokenBuilder */ @BetaApi - public GHAppCreateTokenBuilder permissions(Map permissions) { - Map retMap = new HashMap<>(); - for (Map.Entry entry : permissions.entrySet()) { - retMap.put(entry.getKey(), GitHubRequest.transformEnum(entry.getValue())); - } - builder.with("permissions", retMap); + public GHAppCreateTokenBuilder repositoryIds(List repositoryIds) { + this.builder.with("repository_ids", repositoryIds); return this; } @@ -79,18 +63,34 @@ public GHAppCreateTokenBuilder repositories(List repositories) { } /** - * By default the installation token has access to all repositories that the installation can access. To restrict - * the access to specific repositories, you can provide the repository_ids when creating the token. When you omit - * repository_ids, the response does not contain neither the repositories nor the permissions key. + * Set the permissions granted to the access token. The permissions object includes the permission names and their + * access type. * - * @param repositoryIds - * Array containing the repositories Ids + * @param permissions + * Map containing the permission names and types. * @return a GHAppCreateTokenBuilder */ @BetaApi - public GHAppCreateTokenBuilder repositoryIds(List repositoryIds) { - this.builder.with("repository_ids", repositoryIds); + public GHAppCreateTokenBuilder permissions(Map permissions) { + Map retMap = new HashMap<>(); + for (Map.Entry entry : permissions.entrySet()) { + retMap.put(entry.getKey(), GitHubRequest.transformEnum(entry.getValue())); + } + builder.with("permissions", retMap); return this; } + /** + * Creates an app token with all the parameters. + *

+ * You must use a JWT to access this endpoint. + * + * @return a GHAppInstallationToken + * @throws IOException + * on error + */ + public GHAppInstallationToken create() throws IOException { + return builder.method("POST").withUrlPath(apiUrlTail).fetch(GHAppInstallationToken.class); + } + } diff --git a/src/main/java/org/kohsuke/github/GHAppFromManifest.java b/src/main/java/org/kohsuke/github/GHAppFromManifest.java index 2fa5e3998c..3d6c4cdf20 100644 --- a/src/main/java/org/kohsuke/github/GHAppFromManifest.java +++ b/src/main/java/org/kohsuke/github/GHAppFromManifest.java @@ -8,17 +8,17 @@ */ public class GHAppFromManifest extends GHApp { - private String clientId; - - private String clientSecret; - private String pem; - private String webhookSecret; /** * Create default GHAppFromManifest instance */ public GHAppFromManifest() { } + private String clientId; + private String clientSecret; + private String webhookSecret; + private String pem; + /** * Gets the client id * @@ -38,20 +38,20 @@ public String getClientSecret() { } /** - * Gets the pem + * Gets the webhook secret * - * @return the pem + * @return the webhook secret */ - public String getPem() { - return pem; + public String getWebhookSecret() { + return webhookSecret; } /** - * Gets the webhook secret + * Gets the pem * - * @return the webhook secret + * @return the pem */ - public String getWebhookSecret() { - return webhookSecret; + public String getPem() { + return pem; } } diff --git a/src/main/java/org/kohsuke/github/GHAppInstallation.java b/src/main/java/org/kohsuke/github/GHAppInstallation.java index e92c744e99..c2611e468c 100644 --- a/src/main/java/org/kohsuke/github/GHAppInstallation.java +++ b/src/main/java/org/kohsuke/github/GHAppInstallation.java @@ -1,13 +1,11 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JsonProperty; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.kohsuke.github.internal.EnumUtils; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Collections; import java.util.Date; import java.util.List; @@ -27,103 +25,98 @@ */ public class GHAppInstallation extends GHObject { - private static class GHAppInstallationRepositoryResult extends SearchResult { - private GHRepository[] repositories; - - @Override - GHRepository[] getItems(GitHub root) { - return repositories; - } + /** + * Create default GHAppInstallation instance + */ + public GHAppInstallation() { } + private GHUser account; + @JsonProperty("access_tokens_url") private String accessTokenUrl; - - private GHUser account; + @JsonProperty("repositories_url") + private String repositoriesUrl; @JsonProperty("app_id") private long appId; - private List events; - private String htmlUrl; + @JsonProperty("target_id") + private long targetId; + @JsonProperty("target_type") + private GHTargetType targetType; private Map permissions; - @JsonProperty("repositories_url") - private String repositoriesUrl; - @JsonProperty("repository_selection") - private GHRepositorySelection repositorySelection; + private List events; @JsonProperty("single_file_name") private String singleFileName; + @JsonProperty("repository_selection") + private GHRepositorySelection repositorySelection; + private String htmlUrl; private String suspendedAt; private GHUser suspendedBy; - @JsonProperty("target_id") - private long targetId; - @JsonProperty("target_type") - private GHTargetType targetType; /** - * Create default GHAppInstallation instance + * Gets the html url. + * + * @return the html url */ - public GHAppInstallation() { + public URL getHtmlUrl() { + return GitHubClient.parseURL(htmlUrl); } /** - * Starts a builder that creates a new App Installation Token. - * - *

- * You use the returned builder to set various properties, then call {@link GHAppCreateTokenBuilder#create()} to - * finally create an access token. + * Gets account. * - * @return a GHAppCreateTokenBuilder instance + * @return the account */ - public GHAppCreateTokenBuilder createToken() { - return new GHAppCreateTokenBuilder(root(), String.format("/app/installations/%d/access_tokens", getId())); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getAccount() { + return account; } /** - * Starts a builder that creates a new App Installation Token. - * - *

- * You use the returned builder to set various properties, then call {@link GHAppCreateTokenBuilder#create()} to - * finally create an access token. + * Gets access token url. * - * @param permissions - * map of permissions for the created token - * @return a GHAppCreateTokenBuilder instance - * @deprecated Use {@link GHAppInstallation#createToken()} instead. + * @return the access token url */ - @Deprecated - public GHAppCreateTokenBuilder createToken(Map permissions) { - return createToken().permissions(permissions); + public String getAccessTokenUrl() { + return accessTokenUrl; } /** - * Delete a Github App installation - *

- * You must use a JWT to access this endpoint. + * Gets repositories url. * - * @throws IOException - * on error - * @see Delete an installation + * @return the repositories url */ - public void deleteInstallation() throws IOException { - root().createRequest().method("DELETE").withUrlPath(String.format("/app/installations/%d", getId())).send(); + public String getRepositoriesUrl() { + return repositoriesUrl; } /** - * Gets access token url. + * List repositories that this app installation can access. * - * @return the access token url + * @return the paged iterable + * @deprecated This method cannot work on a {@link GHAppInstallation} retrieved from + * {@link GHApp#listInstallations()} (for example), except when resorting to unsupported hacks involving + * setRoot(GitHub) to switch from an application client to an installation client. This method will be + * removed. You should instead use an installation client (with an installation token, not a JWT), + * retrieve a {@link GHAuthenticatedAppInstallation} from {@link GitHub#getInstallation()}, then call + * {@link GHAuthenticatedAppInstallation#listRepositories()}. */ - public String getAccessTokenUrl() { - return accessTokenUrl; + @Deprecated + public PagedSearchIterable listRepositories() { + GitHubRequest request; + + request = root().createRequest().withUrlPath("/installation/repositories").build(); + + return new PagedSearchIterable<>(root(), request, GHAppInstallationRepositoryResult.class); } - /** - * Gets account. - * - * @return the account - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getAccount() { - return account; + private static class GHAppInstallationRepositoryResult extends SearchResult { + private GHRepository[] repositories; + + @Override + GHRepository[] getItems(GitHub root) { + return repositories; + } } /** @@ -136,44 +129,21 @@ public long getAppId() { } /** - * Gets events. - * - * @return the events - */ - public List getEvents() { - return events.stream() - .map(e -> EnumUtils.getEnumOrDefault(GHEvent.class, e, GHEvent.UNKNOWN)) - .collect(Collectors.toList()); - } - - /** - * Gets the html url. + * Gets target id. * - * @return the html url + * @return the target id */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public long getTargetId() { + return targetId; } /** - * Shows whether the user or organization account actively subscribes to a plan listed by the authenticated GitHub - * App. When someone submits a plan change that won't be processed until the end of their billing cycle, you will - * also see the upcoming pending change. - * - *

- * GitHub Apps must use a JWT to access this endpoint. - *

- * OAuth Apps must use basic authentication with their client ID and client secret to access this endpoint. + * Gets target type. * - * @return a GHMarketplaceAccountPlan instance - * @throws IOException - * it may throw an {@link IOException} - * @see Get - * a subscription plan for an account + * @return the target type */ - public GHMarketplaceAccountPlan getMarketplaceAccount() throws IOException { - return new GHMarketplacePlanForAccountBuilder(root(), account.getId()).createRequest(); + public GHTargetType getTargetType() { + return targetType; } /** @@ -186,30 +156,32 @@ public Map getPermissions() { } /** - * Gets repositories url. + * Gets events. * - * @return the repositories url + * @return the events */ - public String getRepositoriesUrl() { - return repositoriesUrl; + public List getEvents() { + return events.stream() + .map(e -> EnumUtils.getEnumOrDefault(GHEvent.class, e, GHEvent.UNKNOWN)) + .collect(Collectors.toList()); } /** - * Gets repository selection. + * Gets single file name. * - * @return the repository selection + * @return the single file name */ - public GHRepositorySelection getRepositorySelection() { - return repositorySelection; + public String getSingleFileName() { + return singleFileName; } /** - * Gets single file name. + * Gets repository selection. * - * @return the single file name + * @return the repository selection */ - public String getSingleFileName() { - return singleFileName; + public GHRepositorySelection getRepositorySelection() { + return repositorySelection; } /** @@ -217,9 +189,8 @@ public String getSingleFileName() { * * @return the suspended at */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getSuspendedAt() { - return GitHubClient.parseInstant(suspendedAt); + public Date getSuspendedAt() { + return GitHubClient.parseDate(suspendedAt); } /** @@ -233,40 +204,66 @@ public GHUser getSuspendedBy() { } /** - * Gets target id. + * Delete a Github App installation + *

+ * You must use a JWT to access this endpoint. * - * @return the target id + * @throws IOException + * on error + * @see Delete an installation */ - public long getTargetId() { - return targetId; + public void deleteInstallation() throws IOException { + root().createRequest().method("DELETE").withUrlPath(String.format("/app/installations/%d", getId())).send(); } /** - * Gets target type. + * Starts a builder that creates a new App Installation Token. * - * @return the target type + *

+ * You use the returned builder to set various properties, then call {@link GHAppCreateTokenBuilder#create()} to + * finally create an access token. + * + * @param permissions + * map of permissions for the created token + * @return a GHAppCreateTokenBuilder instance + * @deprecated Use {@link GHAppInstallation#createToken()} instead. */ - public GHTargetType getTargetType() { - return targetType; + @Deprecated + public GHAppCreateTokenBuilder createToken(Map permissions) { + return createToken().permissions(permissions); } /** - * List repositories that this app installation can access. + * Starts a builder that creates a new App Installation Token. * - * @return the paged iterable - * @deprecated This method cannot work on a {@link GHAppInstallation} retrieved from - * {@link GHApp#listInstallations()} (for example), except when resorting to unsupported hacks involving - * setRoot(GitHub) to switch from an application client to an installation client. This method will be - * removed. You should instead use an installation client (with an installation token, not a JWT), - * retrieve a {@link GHAuthenticatedAppInstallation} from {@link GitHub#getInstallation()}, then call - * {@link GHAuthenticatedAppInstallation#listRepositories()}. + *

+ * You use the returned builder to set various properties, then call {@link GHAppCreateTokenBuilder#create()} to + * finally create an access token. + * + * @return a GHAppCreateTokenBuilder instance */ - @Deprecated - public PagedSearchIterable listRepositories() { - GitHubRequest request; - - request = root().createRequest().withUrlPath("/installation/repositories").build(); + public GHAppCreateTokenBuilder createToken() { + return new GHAppCreateTokenBuilder(root(), String.format("/app/installations/%d/access_tokens", getId())); + } - return new PagedSearchIterable<>(root(), request, GHAppInstallationRepositoryResult.class); + /** + * Shows whether the user or organization account actively subscribes to a plan listed by the authenticated GitHub + * App. When someone submits a plan change that won't be processed until the end of their billing cycle, you will + * also see the upcoming pending change. + * + *

+ * GitHub Apps must use a JWT to access this endpoint. + *

+ * OAuth Apps must use basic authentication with their client ID and client secret to access this endpoint. + * + * @return a GHMarketplaceAccountPlan instance + * @throws IOException + * it may throw an {@link IOException} + * @see Get + * a subscription plan for an account + */ + public GHMarketplaceAccountPlan getMarketplaceAccount() throws IOException { + return new GHMarketplacePlanForAccountBuilder(root(), account.getId()).createRequest(); } } diff --git a/src/main/java/org/kohsuke/github/GHAppInstallationRequest.java b/src/main/java/org/kohsuke/github/GHAppInstallationRequest.java deleted file mode 100644 index 44ace753a2..0000000000 --- a/src/main/java/org/kohsuke/github/GHAppInstallationRequest.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.kohsuke.github; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -/** - * A Github App Installation Request. - * - * @author Anuj Hydrabadi - * @see GHApp#listInstallationRequests() GHApp#listInstallationRequests() - */ -public class GHAppInstallationRequest extends GHObject { - private GHOrganization account; - - private GHUser requester; - - /** - * Create default GHAppInstallationRequest instance - */ - public GHAppInstallationRequest() { - } - - /** - * Gets the organization where the app was requested to be installed. - * - * @return the organization where the app was requested to be installed. - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP", "UWF_UNWRITTEN_FIELD" }, justification = "Expected behavior") - public GHOrganization getAccount() { - return account; - } - - /** - * Gets the user who requested the installation. - * - * @return the user who requested the installation. - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP", "UWF_UNWRITTEN_FIELD" }, justification = "Expected behavior") - public GHUser getRequester() { - return requester; - } - -} diff --git a/src/main/java/org/kohsuke/github/GHAppInstallationToken.java b/src/main/java/org/kohsuke/github/GHAppInstallationToken.java index 3d268cf38a..f69144bbd4 100644 --- a/src/main/java/org/kohsuke/github/GHAppInstallationToken.java +++ b/src/main/java/org/kohsuke/github/GHAppInstallationToken.java @@ -1,8 +1,6 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; - -import java.time.Instant; +import java.io.IOException; import java.util.*; // TODO: Auto-generated Javadoc @@ -14,29 +12,19 @@ */ public class GHAppInstallationToken extends GitHubInteractiveObject { - private Map permissions; - - private List repositories; - - private GHRepositorySelection repositorySelection; - private String token; - /** The expires at. */ - protected String expiresAt; /** * Create default GHAppInstallationToken instance */ public GHAppInstallationToken() { } - /** - * Gets expires at. - * - * @return date when this token expires - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getExpiresAt() { - return GitHubClient.parseInstant(expiresAt); - } + private String token; + + /** The expires at. */ + protected String expires_at; + private Map permissions; + private List repositories; + private GHRepositorySelection repositorySelection; /** * Gets permissions. @@ -47,6 +35,15 @@ public Map getPermissions() { return Collections.unmodifiableMap(permissions); } + /** + * Gets token. + * + * @return the token + */ + public String getToken() { + return token; + } + /** * Gets repositories. * @@ -66,11 +63,13 @@ public GHRepositorySelection getRepositorySelection() { } /** - * Gets token. + * Gets expires at. * - * @return the token + * @return date when this token expires + * @throws IOException + * on error */ - public String getToken() { - return token; + public Date getExpiresAt() throws IOException { + return GitHubClient.parseDate(expires_at); } } diff --git a/src/main/java/org/kohsuke/github/GHAppInstallationsIterable.java b/src/main/java/org/kohsuke/github/GHAppInstallationsIterable.java index fc89d371ee..8a150de1fb 100644 --- a/src/main/java/org/kohsuke/github/GHAppInstallationsIterable.java +++ b/src/main/java/org/kohsuke/github/GHAppInstallationsIterable.java @@ -12,8 +12,8 @@ class GHAppInstallationsIterable extends PagedIterable { /** The Constant APP_INSTALLATIONS_URL. */ public static final String APP_INSTALLATIONS_URL = "/user/installations"; - private GHAppInstallationsPage result; private final transient GitHub root; + private GHAppInstallationsPage result; /** * Instantiates a new GH app installations iterable. diff --git a/src/main/java/org/kohsuke/github/GHAppInstallationsPage.java b/src/main/java/org/kohsuke/github/GHAppInstallationsPage.java index cd8f9a1f7e..9a29832941 100644 --- a/src/main/java/org/kohsuke/github/GHAppInstallationsPage.java +++ b/src/main/java/org/kohsuke/github/GHAppInstallationsPage.java @@ -5,8 +5,8 @@ * Represents the one page of GHAppInstallations. */ class GHAppInstallationsPage { + private int total_count; private GHAppInstallation[] installations; - private int totalCount; /** * Gets the total count. @@ -14,7 +14,7 @@ class GHAppInstallationsPage { * @return the total count */ public int getTotalCount() { - return totalCount; + return total_count; } /** diff --git a/src/main/java/org/kohsuke/github/GHArtifact.java b/src/main/java/org/kohsuke/github/GHArtifact.java index 21c16836f8..cc37a5bf4d 100644 --- a/src/main/java/org/kohsuke/github/GHArtifact.java +++ b/src/main/java/org/kohsuke/github/GHArtifact.java @@ -1,14 +1,12 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import org.kohsuke.github.function.InputStreamFunction; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Date; import java.util.Objects; @@ -22,47 +20,38 @@ */ public class GHArtifact extends GHObject { - private String archiveDownloadUrl; - - private boolean expired; - - private String expiresAt; - private String name; - // Not provided by the API. - @JsonIgnore - private GHRepository owner; - private long sizeInBytes; /** * Create default GHArtifact instance */ public GHArtifact() { } + // Not provided by the API. + @JsonIgnore + private GHRepository owner; + + private String name; + private long sizeInBytes; + private String archiveDownloadUrl; + private boolean expired; + private String expiresAt; + /** - * Deletes the artifact. + * Gets the name. * - * @throws IOException - * the io exception + * @return the name */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + public String getName() { + return name; } /** - * Downloads the artifact. + * Gets the size of the artifact in bytes. * - * @param - * the type of result - * @param streamFunction - * The {@link InputStreamFunction} that will process the stream - * @return the result of reading the stream. - * @throws IOException - * The IO exception. + * @return the size */ - public T download(InputStreamFunction streamFunction) throws IOException { - requireNonNull(streamFunction, "Stream function must not be null"); - - return root().createRequest().method("GET").withUrlPath(getApiRoute(), "zip").fetchStream(streamFunction); + public long getSizeInBytes() { + return sizeInBytes; } /** @@ -75,22 +64,21 @@ public URL getArchiveDownloadUrl() { } /** - * Gets the date at which this artifact will expire. + * If this artifact has expired. * - * @return the date of expiration + * @return if the artifact has expired */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getExpiresAt() { - return GitHubClient.parseInstant(expiresAt); + public boolean isExpired() { + return expired; } /** - * Gets the name. + * Gets the date at which this artifact will expire. * - * @return the name + * @return the date of expiration */ - public String getName() { - return name; + public Date getExpiresAt() { + return GitHubClient.parseDate(expiresAt); } /** @@ -104,21 +92,30 @@ public GHRepository getRepository() { } /** - * Gets the size of the artifact in bytes. + * Deletes the artifact. * - * @return the size + * @throws IOException + * the io exception */ - public long getSizeInBytes() { - return sizeInBytes; + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } /** - * If this artifact has expired. + * Downloads the artifact. * - * @return if the artifact has expired + * @param + * the type of result + * @param streamFunction + * The {@link InputStreamFunction} that will process the stream + * @return the result of reading the stream. + * @throws IOException + * The IO exception. */ - public boolean isExpired() { - return expired; + public T download(InputStreamFunction streamFunction) throws IOException { + requireNonNull(streamFunction, "Stream function must not be null"); + + return root().createRequest().method("GET").withUrlPath(getApiRoute(), "zip").fetchStream(streamFunction); } private String getApiRoute() { diff --git a/src/main/java/org/kohsuke/github/GHArtifactsPage.java b/src/main/java/org/kohsuke/github/GHArtifactsPage.java index 8b3675bb11..4ef5878699 100644 --- a/src/main/java/org/kohsuke/github/GHArtifactsPage.java +++ b/src/main/java/org/kohsuke/github/GHArtifactsPage.java @@ -9,8 +9,8 @@ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") class GHArtifactsPage { + private int total_count; private GHArtifact[] artifacts; - private int totalCount; /** * Gets the total count. @@ -18,7 +18,7 @@ class GHArtifactsPage { * @return the total count */ public int getTotalCount() { - return totalCount; + return total_count; } /** diff --git a/src/main/java/org/kohsuke/github/GHAsset.java b/src/main/java/org/kohsuke/github/GHAsset.java index 8ad0455483..3f9c8f420c 100644 --- a/src/main/java/org/kohsuke/github/GHAsset.java +++ b/src/main/java/org/kohsuke/github/GHAsset.java @@ -13,63 +13,41 @@ public class GHAsset extends GHObject { /** - * Wrap gh asset [ ]. - * - * @param assets - * the assets - * @param release - * the release - * @return the gh asset [ ] + * Create default GHAsset instance */ - public static GHAsset[] wrap(GHAsset[] assets, GHRelease release) { - for (GHAsset aTo : assets) { - aTo.wrap(release); - } - return assets; + public GHAsset() { } - private String browserDownloadUrl; - private String contentType; - private long downloadCount; - private String label; - private String name; - private long size; - private String state; /** The owner. */ GHRepository owner; + private String name; + private String label; + private String state; + private String content_type; + private long size; + private long download_count; + private String browser_download_url; /** - * Create default GHAsset instance + * Gets content type. + * + * @return the content type */ - public GHAsset() { + public String getContentType() { + return content_type; } /** - * Delete. + * Sets content type. * + * @param contentType + * the content type * @throws IOException * the io exception */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); - } - - /** - * Gets browser download url. - * - * @return the browser download url - */ - public String getBrowserDownloadUrl() { - return browserDownloadUrl; - } - - /** - * Gets content type. - * - * @return the content type - */ - public String getContentType() { - return contentType; + public void setContentType(String contentType) throws IOException { + edit("content_type", contentType); + this.content_type = contentType; } /** @@ -78,7 +56,7 @@ public String getContentType() { * @return the download count */ public long getDownloadCount() { - return downloadCount; + return download_count; } /** @@ -90,6 +68,19 @@ public String getLabel() { return label; } + /** + * Sets label. + * + * @param label + * the label + * @throws IOException + * the io exception + */ + public void setLabel(String label) throws IOException { + edit("label", label); + this.label = label; + } + /** * Gets name. * @@ -128,33 +119,26 @@ public String getState() { } /** - * Sets content type. + * Gets browser download url. * - * @param contentType - * the content type - * @throws IOException - * the io exception + * @return the browser download url */ - public void setContentType(String contentType) throws IOException { - edit("content_type", contentType); - this.contentType = contentType; + public String getBrowserDownloadUrl() { + return browser_download_url; + } + + private void edit(String key, Object value) throws IOException { + root().createRequest().with(key, value).method("PATCH").withUrlPath(getApiRoute()).send(); } /** - * Sets label. + * Delete. * - * @param label - * the label * @throws IOException * the io exception */ - public void setLabel(String label) throws IOException { - edit("label", label); - this.label = label; - } - - private void edit(String key, Object value) throws IOException { - root().createRequest().with(key, value).method("PATCH").withUrlPath(getApiRoute()).send(); + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } private String getApiRoute() { @@ -172,4 +156,20 @@ GHAsset wrap(GHRelease release) { this.owner = release.getOwner(); return this; } + + /** + * Wrap gh asset [ ]. + * + * @param assets + * the assets + * @param release + * the release + * @return the gh asset [ ] + */ + public static GHAsset[] wrap(GHAsset[] assets, GHRelease release) { + for (GHAsset aTo : assets) { + aTo.wrap(release); + } + return assets; + } } diff --git a/src/main/java/org/kohsuke/github/GHAuthenticatedAppInstallation.java b/src/main/java/org/kohsuke/github/GHAuthenticatedAppInstallation.java index 73d55ba4c1..7c3fc8257b 100644 --- a/src/main/java/org/kohsuke/github/GHAuthenticatedAppInstallation.java +++ b/src/main/java/org/kohsuke/github/GHAuthenticatedAppInstallation.java @@ -10,15 +10,6 @@ */ public class GHAuthenticatedAppInstallation extends GitHubInteractiveObject { - private static class GHAuthenticatedAppInstallationRepositoryResult extends SearchResult { - private GHRepository[] repositories; - - @Override - GHRepository[] getItems(GitHub root) { - return repositories; - } - } - /** * Instantiates a new GH authenticated app installation. * @@ -42,4 +33,13 @@ public PagedSearchIterable listRepositories() { return new PagedSearchIterable<>(root(), request, GHAuthenticatedAppInstallationRepositoryResult.class); } + private static class GHAuthenticatedAppInstallationRepositoryResult extends SearchResult { + private GHRepository[] repositories; + + @Override + GHRepository[] getItems(GitHub root) { + return repositories; + } + } + } diff --git a/src/main/java/org/kohsuke/github/GHAuthorization.java b/src/main/java/org/kohsuke/github/GHAuthorization.java index 9768de3063..1dd22edbeb 100644 --- a/src/main/java/org/kohsuke/github/GHAuthorization.java +++ b/src/main/java/org/kohsuke/github/GHAuthorization.java @@ -17,110 +17,102 @@ */ public class GHAuthorization extends GHObject { - @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD" }, - justification = "JSON API") - private static class App { - private String name; - // private String client_id; not yet used - private String url; + /** + * Create default GHAuthorization instance + */ + public GHAuthorization() { } - /** The Constant ADMIN_KEY. */ - public static final String ADMIN_KEY = "admin:public_key"; + /** The Constant USER. */ + public static final String USER = "user"; - /** The Constant ADMIN_ORG. */ - public static final String ADMIN_ORG = "admin:org"; + /** The Constant USER_EMAIL. */ + public static final String USER_EMAIL = "user:email"; - /** The Constant AMIN_HOOK. */ - public static final String AMIN_HOOK = "admin:repo_hook"; + /** The Constant USER_FOLLOW. */ + public static final String USER_FOLLOW = "user:follow"; + + /** The Constant PUBLIC_REPO. */ + public static final String PUBLIC_REPO = "public_repo"; + + /** The Constant REPO. */ + public static final String REPO = "repo"; + + /** The Constant REPO_STATUS. */ + public static final String REPO_STATUS = "repo:status"; /** The Constant DELETE_REPO. */ public static final String DELETE_REPO = "delete_repo"; - /** The Constant GIST. */ - public static final String GIST = "gist"; - /** The Constant NOTIFICATIONS. */ public static final String NOTIFICATIONS = "notifications"; - /** The Constant PUBLIC_REPO. */ - public static final String PUBLIC_REPO = "public_repo"; + /** The Constant GIST. */ + public static final String GIST = "gist"; /** The Constant READ_HOOK. */ public static final String READ_HOOK = "read:repo_hook"; - /** The Constant READ_KEY. */ - public static final String READ_KEY = "read:public_key"; + /** The Constant WRITE_HOOK. */ + public static final String WRITE_HOOK = "write:repo_hook"; + + /** The Constant AMIN_HOOK. */ + public static final String AMIN_HOOK = "admin:repo_hook"; /** The Constant READ_ORG. */ public static final String READ_ORG = "read:org"; - /** The Constant REPO. */ - public static final String REPO = "repo"; - - /** The Constant REPO_STATUS. */ - public static final String REPO_STATUS = "repo:status"; - - /** The Constant USER. */ - public static final String USER = "user"; - - /** The Constant USER_EMAIL. */ - public static final String USER_EMAIL = "user:email"; + /** The Constant WRITE_ORG. */ + public static final String WRITE_ORG = "write:org"; - /** The Constant USER_FOLLOW. */ - public static final String USER_FOLLOW = "user:follow"; + /** The Constant ADMIN_ORG. */ + public static final String ADMIN_ORG = "admin:org"; - /** The Constant WRITE_HOOK. */ - public static final String WRITE_HOOK = "write:repo_hook"; + /** The Constant READ_KEY. */ + public static final String READ_KEY = "read:public_key"; /** The Constant WRITE_KEY. */ public static final String WRITE_KEY = "write:public_key"; - /** The Constant WRITE_ORG. */ - public static final String WRITE_ORG = "write:org"; + /** The Constant ADMIN_KEY. */ + public static final String ADMIN_KEY = "admin:public_key"; + private List scopes; + private String token; + private String token_last_eight; + private String hashed_token; private App app; + private String note; + private String note_url; private String fingerprint; // TODO add some user class for https://developer.github.com/v3/oauth_authorizations/#check-an-authorization ? // private GHUser user; - private String hashedToken; - private String note; - private String noteUrl; - private List scopes; - private String token; - private String tokenLastEight; - - /** - * Create default GHAuthorization instance - */ - public GHAuthorization() { - } /** - * Gets app name. + * Gets scopes. * - * @return the app name + * @return the scopes */ - public String getAppName() { - return app.name; + public List getScopes() { + return Collections.unmodifiableList(scopes); } /** - * Gets app url. + * Gets token. * - * @return the app url + * @return the token */ - public URL getAppUrl() { - return GitHubClient.parseURL(app.url); + public String getToken() { + return token; } /** - * Gets fingerprint. + * Gets token last eight. * - * @return the fingerprint + * @return the token last eight */ - public String getFingerprint() { - return fingerprint; + public String getTokenLastEight() { + return token_last_eight; } /** @@ -129,51 +121,59 @@ public String getFingerprint() { * @return the hashed token */ public String getHashedToken() { - return hashedToken; + return hashed_token; } /** - * Gets note. + * Gets app url. * - * @return the note + * @return the app url */ - public String getNote() { - return note; + public URL getAppUrl() { + return GitHubClient.parseURL(app.url); } /** - * Gets note url. + * Gets app name. * - * @return the note url + * @return the app name */ - public URL getNoteUrl() { - return GitHubClient.parseURL(noteUrl); + public String getAppName() { + return app.name; } /** - * Gets scopes. + * Gets note. * - * @return the scopes + * @return the note */ - public List getScopes() { - return Collections.unmodifiableList(scopes); + public String getNote() { + return note; } /** - * Gets token. + * Gets note url. * - * @return the token + * @return the note url */ - public String getToken() { - return token; + public URL getNoteUrl() { + return GitHubClient.parseURL(note_url); } /** - * Gets token last eight. + * Gets fingerprint. * - * @return the token last eight + * @return the fingerprint */ - public String getTokenLastEight() { - return tokenLastEight; + public String getFingerprint() { + return fingerprint; + } + + @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD" }, + justification = "JSON API") + private static class App { + private String url; + private String name; + // private String client_id; not yet used } } diff --git a/src/main/java/org/kohsuke/github/GHAutolink.java b/src/main/java/org/kohsuke/github/GHAutolink.java deleted file mode 100644 index 9fe9c6a791..0000000000 --- a/src/main/java/org/kohsuke/github/GHAutolink.java +++ /dev/null @@ -1,100 +0,0 @@ -package org.kohsuke.github; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -import java.io.IOException; - -/** - * Represents a GitHub repository autolink reference. - * - * @author Alaurant - * @see GHAutolinkBuilder - * @see GHRepository#listAutolinks() GHRepository#listAutolinks() - * @see Repository autolinks API - */ -public class GHAutolink { - - private int id; - private boolean isAlphanumeric; - private String keyPrefix; - private GHRepository owner; - private String urlTemplate; - - /** - * Instantiates a new Gh autolink. - */ - public GHAutolink() { - } - - /** - * Deletes this autolink - * - * @throws IOException - * if the deletion fails - */ - public void delete() throws IOException { - owner.root() - .createRequest() - .method("DELETE") - .withUrlPath(String.format("/repos/%s/%s/autolinks/%d", owner.getOwnerName(), owner.getName(), getId())) - .send(); - } - - /** - * Gets the autolink ID - * - * @return the id - */ - public int getId() { - return id; - } - - /** - * Gets the key prefix used to identify issues/PR references - * - * @return the key prefix string - */ - public String getKeyPrefix() { - return keyPrefix; - } - - /** - * Gets the repository that owns this autolink - * - * @return the repository instance - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return owner; - } - - /** - * Gets the URL template that will be used for matching - * - * @return the URL template string - */ - public String getUrlTemplate() { - return urlTemplate; - } - - /** - * Checks if the autolink uses alphanumeric values - * - * @return true if alphanumeric, false otherwise - */ - public boolean isAlphanumeric() { - return isAlphanumeric; - } - - /** - * Wraps this autolink with its owner repository. - * - * @param owner - * the repository that owns this autolink - * @return this instance - */ - GHAutolink lateBind(GHRepository owner) { - this.owner = owner; - return this; - } -} diff --git a/src/main/java/org/kohsuke/github/GHAutolinkBuilder.java b/src/main/java/org/kohsuke/github/GHAutolinkBuilder.java deleted file mode 100644 index c5726ced6e..0000000000 --- a/src/main/java/org/kohsuke/github/GHAutolinkBuilder.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.kohsuke.github; - -import java.io.IOException; - -// TODO: Auto-generated Javadoc -/** - * The type Gh autolink builder. - * - * @see GHRepository#createAutolink() - * @see GHAutolink - */ -public class GHAutolinkBuilder { - - private Boolean isAlphanumeric; - private String keyPrefix; - private final GHRepository repo; - private final Requester req; - private String urlTemplate; - - /** - * Instantiates a new Gh autolink builder. - * - * @param repo - * the repo - */ - GHAutolinkBuilder(GHRepository repo) { - this.repo = repo; - req = repo.root().createRequest(); - } - - /** - * Create gh autolink. - * - * @return the gh autolink - * @throws IOException - * the io exception - */ - public GHAutolink create() throws IOException { - GHAutolink autolink = req.method("POST") - .with("key_prefix", keyPrefix) - .with("url_template", urlTemplate) - .with("is_alphanumeric", isAlphanumeric) - .withHeader("Accept", "application/vnd.github+json") - .withUrlPath(getApiTail()) - .fetch(GHAutolink.class); - - return autolink.lateBind(repo); - } - - /** - * With is alphanumeric gh autolink builder. - * - * @param isAlphanumeric - * the is alphanumeric - * @return the gh autolink builder - */ - public GHAutolinkBuilder withIsAlphanumeric(boolean isAlphanumeric) { - this.isAlphanumeric = isAlphanumeric; - return this; - } - - /** - * With key prefix gh autolink builder. - * - * @param keyPrefix - * the key prefix - * @return the gh autolink builder - */ - public GHAutolinkBuilder withKeyPrefix(String keyPrefix) { - this.keyPrefix = keyPrefix; - return this; - } - - /** - * With url template gh autolink builder. - * - * @param urlTemplate - * the url template - * @return the gh autolink builder - */ - public GHAutolinkBuilder withUrlTemplate(String urlTemplate) { - this.urlTemplate = urlTemplate; - return this; - } - - private String getApiTail() { - return String.format("/repos/%s/%s/autolinks", repo.getOwnerName(), repo.getName()); - } - -} diff --git a/src/main/java/org/kohsuke/github/GHBlob.java b/src/main/java/org/kohsuke/github/GHBlob.java index 31c83b6ff4..2fc168ec69 100644 --- a/src/main/java/org/kohsuke/github/GHBlob.java +++ b/src/main/java/org/kohsuke/github/GHBlob.java @@ -17,31 +17,22 @@ */ public class GHBlob { - private String content, encoding, url, sha; - - private long size; /** * Create default GHBlob instance */ public GHBlob() { } - /** - * Gets content. - * - * @return Encoded content. You probably want {@link #read()} - */ - public String getContent() { - return content; - } + private String content, encoding, url, sha; + private long size; /** - * Gets encoding. + * Gets url. * - * @return the encoding + * @return API URL of this blob. */ - public String getEncoding() { - return encoding; + public URL getUrl() { + return GitHubClient.parseURL(url); } /** @@ -63,12 +54,21 @@ public long getSize() { } /** - * Gets url. + * Gets encoding. * - * @return API URL of this blob. + * @return the encoding */ - public URL getUrl() { - return GitHubClient.parseURL(url); + public String getEncoding() { + return encoding; + } + + /** + * Gets content. + * + * @return Encoded content. You probably want {@link #read()} + */ + public String getContent() { + return content; } /** diff --git a/src/main/java/org/kohsuke/github/GHBlobBuilder.java b/src/main/java/org/kohsuke/github/GHBlobBuilder.java index 237768e503..187867689b 100644 --- a/src/main/java/org/kohsuke/github/GHBlobBuilder.java +++ b/src/main/java/org/kohsuke/github/GHBlobBuilder.java @@ -22,6 +22,19 @@ public class GHBlobBuilder { req = repo.root().createRequest(); } + /** + * Configures a blob with the specified text {@code content}. + * + * @param content + * string text of the blob + * @return a GHBlobBuilder + */ + public GHBlobBuilder textContent(String content) { + req.with("content", content); + req.with("encoding", "utf-8"); + return this; + } + /** * Configures a blob with the specified binary {@code content}. * @@ -36,6 +49,10 @@ public GHBlobBuilder binaryContent(byte[] content) { return this; } + private String getApiTail() { + return String.format("/repos/%s/%s/git/blobs", repo.getOwnerName(), repo.getName()); + } + /** * Creates a blob based on the parameters specified thus far. * @@ -46,21 +63,4 @@ public GHBlobBuilder binaryContent(byte[] content) { public GHBlob create() throws IOException { return req.method("POST").withUrlPath(getApiTail()).fetch(GHBlob.class); } - - /** - * Configures a blob with the specified text {@code content}. - * - * @param content - * string text of the blob - * @return a GHBlobBuilder - */ - public GHBlobBuilder textContent(String content) { - req.with("content", content); - req.with("encoding", "utf-8"); - return this; - } - - private String getApiTail() { - return String.format("/repos/%s/%s/git/blobs", repo.getOwnerName(), repo.getName()); - } } diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index c18bd23aa7..f803c67e70 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -21,63 +21,55 @@ "URF_UNREAD_FIELD" }, justification = "JSON API") public class GHBranch extends GitHubInteractiveObject { - /** - * The type Commit. - */ - public static class Commit { - - /** The sha. */ - String sha; - - /** The url. */ - @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") - String url; - - /** - * Create default Commit instance - */ - public Commit() { - } - } + private GHRepository owner; - private Commit commit; private String name; - private GHRepository owner; + private Commit commit; @JsonProperty("protected") private boolean protection; - - private String protectionUrl; + private String protection_url; /** * Instantiates a new GH branch. * * @param name * the name + * @throws Exception + * the exception */ @JsonCreator - GHBranch(@JsonProperty(value = "name", required = true) String name) { + GHBranch(@JsonProperty(value = "name", required = true) String name) throws Exception { Objects.requireNonNull(name); this.name = name; } /** - * Disables branch protection and allows anyone with push access to push changes. - * - * @throws IOException - * if disabling protection fails + * The type Commit. */ - public void disableProtection() throws IOException { - root().createRequest().method("DELETE").setRawUrlPath(protectionUrl).send(); + public static class Commit { + + /** + * Create default Commit instance + */ + public Commit() { + } + + /** The sha. */ + String sha; + + /** The url. */ + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") + String url; } /** - * Enables branch protection to control what commit statuses are required to push. + * Gets owner. * - * @return GHBranchProtectionBuilder for enabling protection - * @see GHCommitStatus#getContext() GHCommitStatus#getContext() + * @return the repository that this branch is in. */ - public GHBranchProtectionBuilder enableProtection() { - return new GHBranchProtectionBuilder(this); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getOwner() { + return owner; } /** @@ -90,13 +82,21 @@ public String getName() { } /** - * Gets owner. + * Is protected boolean. * - * @return the repository that this branch is in. + * @return true if the push to this branch is restricted via branch protection. */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return owner; + public boolean isProtected() { + return protection; + } + + /** + * Gets protection url. + * + * @return API URL that deals with the protection of this branch. + */ + public URL getProtectionUrl() { + return GitHubClient.parseURL(protection_url); } /** @@ -107,34 +107,36 @@ public GHRepository getOwner() { * the io exception */ public GHBranchProtection getProtection() throws IOException { - return root().createRequest().setRawUrlPath(protectionUrl).fetch(GHBranchProtection.class); + return root().createRequest().setRawUrlPath(protection_url).fetch(GHBranchProtection.class); } /** - * Gets protection url. + * Gets sha 1. * - * @return API URL that deals with the protection of this branch. + * @return The SHA1 of the commit that this branch currently points to. */ - public URL getProtectionUrl() { - return GitHubClient.parseURL(protectionUrl); + public String getSHA1() { + return commit.sha; } /** - * Gets sha 1. + * Disables branch protection and allows anyone with push access to push changes. * - * @return The SHA1 of the commit that this branch currently points to. + * @throws IOException + * if disabling protection fails */ - public String getSHA1() { - return commit.sha; + public void disableProtection() throws IOException { + root().createRequest().method("DELETE").setRawUrlPath(protection_url).send(); } /** - * Is protected boolean. + * Enables branch protection to control what commit statuses are required to push. * - * @return true if the push to this branch is restricted via branch protection. + * @return GHBranchProtectionBuilder for enabling protection + * @see GHCommitStatus#getContext() GHCommitStatus#getContext() */ - public boolean isProtected() { - return protection; + public GHBranchProtectionBuilder enableProtection() { + return new GHBranchProtectionBuilder(this); } /** @@ -190,6 +192,15 @@ public GHCommit merge(String head, String commitMessage) throws IOException { return result; } + /** + * Gets the api route. + * + * @return the api route + */ + String getApiRoute() { + return owner.getApiTailUrl("/branches/" + name); + } + /** * To string. * @@ -201,15 +212,6 @@ public String toString() { return "Branch:" + name + " in " + url; } - /** - * Gets the api route. - * - * @return the api route - */ - String getApiRoute() { - return owner.getApiTailUrl("/branches/" + name); - } - /** * Wrap. * diff --git a/src/main/java/org/kohsuke/github/GHBranchProtection.java b/src/main/java/org/kohsuke/github/GHBranchProtection.java index f5d661459c..8fbdc0d232 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtection.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtection.java @@ -20,20 +20,207 @@ justification = "JSON API") public class GHBranchProtection extends GitHubInteractiveObject { + /** + * Create default GHBranchProtection instance + */ + public GHBranchProtection() { + } + + private static final String REQUIRE_SIGNATURES_URI = "/required_signatures"; + + @JsonProperty + private AllowDeletions allowDeletions; + + @JsonProperty + private AllowForcePushes allowForcePushes; + + @JsonProperty + private AllowForkSyncing allowForkSyncing; + + @JsonProperty + private BlockCreations blockCreations; + + @JsonProperty + private EnforceAdmins enforceAdmins; + + @JsonProperty + private LockBranch lockBranch; + + @JsonProperty + private RequiredConversationResolution requiredConversationResolution; + + @JsonProperty + private RequiredLinearHistory requiredLinearHistory; + + @JsonProperty("required_pull_request_reviews") + private RequiredReviews requiredReviews; + + @JsonProperty + private RequiredStatusChecks requiredStatusChecks; + + @JsonProperty + private Restrictions restrictions; + + @JsonProperty + private String url; + + /** + * Enabled signed commits. + * + * @throws IOException + * the io exception + */ + public void enabledSignedCommits() throws IOException { + requester().method("POST").withUrlPath(url + REQUIRE_SIGNATURES_URI).fetch(RequiredSignatures.class); + } + + /** + * Disable signed commits. + * + * @throws IOException + * the io exception + */ + public void disableSignedCommits() throws IOException { + requester().method("DELETE").withUrlPath(url + REQUIRE_SIGNATURES_URI).send(); + } + + /** + * Gets allow deletions. + * + * @return the enforce admins + */ + public AllowDeletions getAllowDeletions() { + return allowDeletions; + } + + /** + * Gets allow force pushes. + * + * @return the enforce admins + */ + public AllowForcePushes getAllowForcePushes() { + return allowForcePushes; + } + + /** + * Gets allow fork syncing. + * + * @return the enforce admins + */ + public AllowForkSyncing getAllowForkSyncing() { + return allowForkSyncing; + } + + /** + * Gets block creations. + * + * @return the enforce admins + */ + public BlockCreations getBlockCreations() { + return blockCreations; + } + + /** + * Gets enforce admins. + * + * @return the enforce admins + */ + public EnforceAdmins getEnforceAdmins() { + return enforceAdmins; + } + + /** + * Gets lock branch. + * + * @return the enforce admins + */ + public LockBranch getLockBranch() { + return lockBranch; + } + + /** + * Gets required conversation resolution. + * + * @return the enforce admins + */ + public RequiredConversationResolution getRequiredConversationResolution() { + return requiredConversationResolution; + } + + /** + * Gets required linear history. + * + * @return the enforce admins + */ + public RequiredLinearHistory getRequiredLinearHistory() { + return requiredLinearHistory; + } + + /** + * Gets required reviews. + * + * @return the required reviews + */ + public RequiredReviews getRequiredReviews() { + return requiredReviews; + } + + /** + * Gets required signatures. + * + * @return the required signatures + * @throws IOException + * the io exception + */ + public boolean getRequiredSignatures() throws IOException { + return requester().withUrlPath(url + REQUIRE_SIGNATURES_URI).fetch(RequiredSignatures.class).enabled; + } + + /** + * Gets required status checks. + * + * @return the required status checks + */ + public RequiredStatusChecks getRequiredStatusChecks() { + return requiredStatusChecks; + } + + /** + * Gets restrictions. + * + * @return the restrictions + */ + public Restrictions getRestrictions() { + return restrictions; + } + + /** + * Gets url. + * + * @return the url + */ + public String getUrl() { + return url; + } + + private Requester requester() { + return root().createRequest(); + } + /** * The type AllowDeletions. */ public static class AllowDeletions { - @JsonProperty - private boolean enabled; - /** * Create default AllowDeletions instance */ public AllowDeletions() { } + @JsonProperty + private boolean enabled; + /** * Is enabled boolean. * @@ -44,20 +231,69 @@ public boolean isEnabled() { } } + /** + * The type Check. + */ + public static class Check { + private String context; + + @JsonInclude(JsonInclude.Include.NON_NULL) + private Integer appId; + + /** + * no-arg constructor for the serializer + */ + public Check() { + } + + /** + * Regular constructor for use in user business logic + * + * @param context + * the context string of the check + * @param appId + * the application ID the check is supposed to come from. Pass "-1" to explicitly allow any app to + * set the status. Pass "null" to automatically select the GitHub App that has recently provided this + * check. + */ + public Check(String context, Integer appId) { + this.context = context; + this.appId = appId; + } + + /** + * The context string of the check + * + * @return the string + */ + public String getContext() { + return context; + } + + /** + * The application ID the check is supposed to come from. The value "-1" indicates "any source". + * + * @return the integer + */ + public Integer getAppId() { + return appId; + } + } + /** * The type AllowForcePushes. */ public static class AllowForcePushes { - @JsonProperty - private boolean enabled; - /** * Create default AllowForcePushes instance */ public AllowForcePushes() { } + @JsonProperty + private boolean enabled; + /** * Is enabled boolean. * @@ -73,15 +309,15 @@ public boolean isEnabled() { */ public static class AllowForkSyncing { - @JsonProperty - private boolean enabled; - /** * Create default AllowForkSyncing instance */ public AllowForkSyncing() { } + @JsonProperty + private boolean enabled; + /** * Is enabled boolean. * @@ -97,15 +333,15 @@ public boolean isEnabled() { */ public static class BlockCreations { - @JsonProperty - private boolean enabled; - /** * Create default BlockCreations instance */ public BlockCreations() { } + @JsonProperty + private boolean enabled; + /** * Is enabled boolean. * @@ -117,58 +353,15 @@ public boolean isEnabled() { } /** - * The type Check. + * The type EnforceAdmins. */ - public static class Check { - @JsonInclude(JsonInclude.Include.NON_NULL) - private Integer appId; - - private String context; - - /** - * no-arg constructor for the serializer - */ - public Check() { - } - - /** - * Regular constructor for use in user business logic - * - * @param context - * the context string of the check - * @param appId - * the application ID the check is supposed to come from. Pass "-1" to explicitly allow any app to - * set the status. Pass "null" to automatically select the GitHub App that has recently provided this - * check. - */ - public Check(String context, Integer appId) { - this.context = context; - this.appId = appId; - } - - /** - * The application ID the check is supposed to come from. The value "-1" indicates "any source". - * - * @return the integer - */ - public Integer getAppId() { - return appId; - } + public static class EnforceAdmins { /** - * The context string of the check - * - * @return the string + * Create default EnforceAdmins instance */ - public String getContext() { - return context; + public EnforceAdmins() { } - } - - /** - * The type EnforceAdmins. - */ - public static class EnforceAdmins { @JsonProperty private boolean enabled; @@ -176,12 +369,6 @@ public static class EnforceAdmins { @JsonProperty private String url; - /** - * Create default EnforceAdmins instance - */ - public EnforceAdmins() { - } - /** * Gets url. * @@ -206,15 +393,15 @@ public boolean isEnabled() { */ public static class LockBranch { - @JsonProperty - private boolean enabled; - /** * Create default LockBranch instance */ public LockBranch() { } + @JsonProperty + private boolean enabled; + /** * Is enabled boolean. * @@ -230,15 +417,15 @@ public boolean isEnabled() { */ public static class RequiredConversationResolution { - @JsonProperty - private boolean enabled; - /** * Create default RequiredConversationResolution instance */ public RequiredConversationResolution() { } + @JsonProperty + private boolean enabled; + /** * Is enabled boolean. * @@ -254,15 +441,15 @@ public boolean isEnabled() { */ public static class RequiredLinearHistory { - @JsonProperty - private boolean enabled; - /** * Create default RequiredLinearHistory instance */ public RequiredLinearHistory() { } + @JsonProperty + private boolean enabled; + /** * Is enabled boolean. * @@ -278,12 +465,18 @@ public boolean isEnabled() { */ public static class RequiredReviews { - @JsonProperty - private boolean dismissStaleReviews; + /** + * Create default RequiredReviews instance + */ + public RequiredReviews() { + } @JsonProperty("dismissal_restrictions") private Restrictions dismissalRestriction; + @JsonProperty + private boolean dismissStaleReviews; + @JsonProperty private boolean requireCodeOwnerReviews; @@ -296,12 +489,6 @@ public static class RequiredReviews { @JsonProperty private String url; - /** - * Create default RequiredReviews instance - */ - public RequiredReviews() { - } - /** * Gets dismissal restrictions. * @@ -311,15 +498,6 @@ public Restrictions getDismissalRestrictions() { return dismissalRestriction; } - /** - * Gets required reviewers. - * - * @return the required reviewers - */ - public int getRequiredReviewers() { - return requiredReviewers; - } - /** * Gets url. * @@ -352,8 +530,43 @@ public boolean isRequireCodeOwnerReviews() { * * @return the boolean */ - public boolean isRequireLastPushApproval() { - return requireLastPushApproval; + public boolean isRequireLastPushApproval() { + return requireLastPushApproval; + } + + /** + * Gets required reviewers. + * + * @return the required reviewers + */ + public int getRequiredReviewers() { + return requiredReviewers; + } + } + + private static class RequiredSignatures { + @JsonProperty + private boolean enabled; + + @JsonProperty + private String url; + + /** + * Gets url. + * + * @return the url + */ + public String getUrl() { + return url; + } + + /** + * Is enabled boolean. + * + * @return the boolean + */ + public boolean isEnabled() { + return enabled; } } @@ -362,12 +575,18 @@ public boolean isRequireLastPushApproval() { */ public static class RequiredStatusChecks { - @JsonProperty - private Collection checks; + /** + * Create default RequiredStatusChecks instance + */ + public RequiredStatusChecks() { + } @JsonProperty private Collection contexts; + @JsonProperty + private Collection checks; + @JsonProperty private boolean strict; @@ -375,9 +594,12 @@ public static class RequiredStatusChecks { private String url; /** - * Create default RequiredStatusChecks instance + * Gets contexts. + * + * @return the contexts */ - public RequiredStatusChecks() { + public Collection getContexts() { + return Collections.unmodifiableCollection(contexts); } /** @@ -389,15 +611,6 @@ public Collection getChecks() { return Collections.unmodifiableCollection(checks); } - /** - * Gets contexts. - * - * @return the contexts - */ - public Collection getContexts() { - return Collections.unmodifiableCollection(contexts); - } - /** * Gets url. * @@ -422,6 +635,12 @@ public boolean isRequiresBranchUpToDate() { */ public static class Restrictions { + /** + * Create default Restrictions instance + */ + public Restrictions() { + } + @JsonProperty private Collection teams; @@ -435,12 +654,6 @@ public static class Restrictions { private String usersUrl; - /** - * Create default Restrictions instance - */ - public Restrictions() { - } - /** * Gets teams. * @@ -486,217 +699,4 @@ public String getUsersUrl() { return usersUrl; } } - - private static class RequiredSignatures { - @JsonProperty - private boolean enabled; - - @JsonProperty - private String url; - - /** - * Gets url. - * - * @return the url - */ - public String getUrl() { - return url; - } - - /** - * Is enabled boolean. - * - * @return the boolean - */ - public boolean isEnabled() { - return enabled; - } - } - - private static final String REQUIRE_SIGNATURES_URI = "/required_signatures"; - - @JsonProperty - private AllowDeletions allowDeletions; - - @JsonProperty - private AllowForcePushes allowForcePushes; - - @JsonProperty - private AllowForkSyncing allowForkSyncing; - - @JsonProperty - private BlockCreations blockCreations; - - @JsonProperty - private EnforceAdmins enforceAdmins; - - @JsonProperty - private LockBranch lockBranch; - - @JsonProperty - private RequiredConversationResolution requiredConversationResolution; - - @JsonProperty - private RequiredLinearHistory requiredLinearHistory; - - @JsonProperty("required_pull_request_reviews") - private RequiredReviews requiredReviews; - - @JsonProperty - private RequiredStatusChecks requiredStatusChecks; - - @JsonProperty - private Restrictions restrictions; - - @JsonProperty - private String url; - - /** - * Create default GHBranchProtection instance - */ - public GHBranchProtection() { - } - - /** - * Disable signed commits. - * - * @throws IOException - * the io exception - */ - public void disableSignedCommits() throws IOException { - requester().method("DELETE").withUrlPath(url + REQUIRE_SIGNATURES_URI).send(); - } - - /** - * Enabled signed commits. - * - * @throws IOException - * the io exception - */ - public void enabledSignedCommits() throws IOException { - requester().method("POST").withUrlPath(url + REQUIRE_SIGNATURES_URI).fetch(RequiredSignatures.class); - } - - /** - * Gets allow deletions. - * - * @return the enforce admins - */ - public AllowDeletions getAllowDeletions() { - return allowDeletions; - } - - /** - * Gets allow force pushes. - * - * @return the enforce admins - */ - public AllowForcePushes getAllowForcePushes() { - return allowForcePushes; - } - - /** - * Gets allow fork syncing. - * - * @return the enforce admins - */ - public AllowForkSyncing getAllowForkSyncing() { - return allowForkSyncing; - } - - /** - * Gets block creations. - * - * @return the enforce admins - */ - public BlockCreations getBlockCreations() { - return blockCreations; - } - - /** - * Gets enforce admins. - * - * @return the enforce admins - */ - public EnforceAdmins getEnforceAdmins() { - return enforceAdmins; - } - - /** - * Gets lock branch. - * - * @return the enforce admins - */ - public LockBranch getLockBranch() { - return lockBranch; - } - - /** - * Gets required conversation resolution. - * - * @return the enforce admins - */ - public RequiredConversationResolution getRequiredConversationResolution() { - return requiredConversationResolution; - } - - /** - * Gets required linear history. - * - * @return the enforce admins - */ - public RequiredLinearHistory getRequiredLinearHistory() { - return requiredLinearHistory; - } - - /** - * Gets required reviews. - * - * @return the required reviews - */ - public RequiredReviews getRequiredReviews() { - return requiredReviews; - } - - /** - * Gets required signatures. - * - * @return the required signatures - * @throws IOException - * the io exception - */ - public boolean getRequiredSignatures() throws IOException { - return requester().withUrlPath(url + REQUIRE_SIGNATURES_URI).fetch(RequiredSignatures.class).enabled; - } - - /** - * Gets required status checks. - * - * @return the required status checks - */ - public RequiredStatusChecks getRequiredStatusChecks() { - return requiredStatusChecks; - } - - /** - * Gets restrictions. - * - * @return the restrictions - */ - public Restrictions getRestrictions() { - return restrictions; - } - - /** - * Gets url. - * - * @return the url - */ - public String getUrl() { - return url; - } - - private Requester requester() { - return root().createRequest(); - } } diff --git a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java index 5b1521d9f1..c56e7f2197 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java @@ -23,21 +23,11 @@ "URF_UNREAD_FIELD" }, justification = "JSON API") public class GHBranchProtectionBuilder { - private static class Restrictions { - private Set teams = new HashSet(); - private Set users = new HashSet(); - } - - private static class StatusChecks { - final List checks = new ArrayList<>(); - boolean strict; - } private final GHBranch branch; + private Map fields = new HashMap(); private Map prReviews; - private Restrictions restrictions; - private StatusChecks statusChecks; /** @@ -58,8 +48,8 @@ private static class StatusChecks { * the checks * @return the gh branch protection builder */ - public GHBranchProtectionBuilder addRequiredChecks(GHBranchProtection.Check... checks) { - addRequiredStatusChecks(Arrays.asList(checks)); + public GHBranchProtectionBuilder addRequiredStatusChecks(Collection checks) { + getStatusChecks().checks.addAll(checks); return this; } @@ -70,8 +60,8 @@ public GHBranchProtectionBuilder addRequiredChecks(GHBranchProtection.Check... c * the checks * @return the gh branch protection builder */ - public GHBranchProtectionBuilder addRequiredStatusChecks(Collection checks) { - getStatusChecks().checks.addAll(checks); + public GHBranchProtectionBuilder addRequiredChecks(GHBranchProtection.Check... checks) { + addRequiredStatusChecks(Arrays.asList(checks)); return this; } @@ -245,6 +235,18 @@ public GHBranchProtectionBuilder lockBranch(boolean v) { return this; } + /** + * Required reviewers gh branch protection builder. + * + * @param v + * the v + * @return the gh branch protection builder + */ + public GHBranchProtectionBuilder requiredReviewers(int v) { + getPrReviews().put("required_approving_review_count", v); + return this; + } + /** * Require branch is up to date gh branch protection builder. * @@ -308,16 +310,6 @@ public GHBranchProtectionBuilder requireLastPushApproval(boolean v) { return this; } - /** - * Require reviews gh branch protection builder. - * - * @return the gh branch protection builder - */ - public GHBranchProtectionBuilder requireReviews() { - getPrReviews(); - return this; - } - /** * Require all conversations on code to be resolved before a pull request can be merged into a branch that matches * this rule. @@ -365,24 +357,12 @@ public GHBranchProtectionBuilder requiredLinearHistory(boolean v) { } /** - * Required reviewers gh branch protection builder. - * - * @param v - * the v - * @return the gh branch protection builder - */ - public GHBranchProtectionBuilder requiredReviewers(int v) { - getPrReviews().put("required_approving_review_count", v); - return this; - } - - /** - * Restrict push access gh branch protection builder. + * Require reviews gh branch protection builder. * * @return the gh branch protection builder */ - public GHBranchProtectionBuilder restrictPushAccess() { - getRestrictions(); + public GHBranchProtectionBuilder requireReviews() { + getPrReviews(); return this; } @@ -401,6 +381,16 @@ public GHBranchProtectionBuilder restrictReviewDismissals() { return this; } + /** + * Restrict push access gh branch protection builder. + * + * @return the gh branch protection builder + */ + public GHBranchProtectionBuilder restrictPushAccess() { + getRestrictions(); + return this; + } + /** * Team push access gh branch protection builder. * @@ -548,4 +538,14 @@ private StatusChecks getStatusChecks() { private Requester requester() { return branch.root().createRequest(); } + + private static class Restrictions { + private Set teams = new HashSet(); + private Set users = new HashSet(); + } + + private static class StatusChecks { + final List checks = new ArrayList<>(); + boolean strict; + } } diff --git a/src/main/java/org/kohsuke/github/GHBranchSync.java b/src/main/java/org/kohsuke/github/GHBranchSync.java index 47b1a34158..c6823abd51 100644 --- a/src/main/java/org/kohsuke/github/GHBranchSync.java +++ b/src/main/java/org/kohsuke/github/GHBranchSync.java @@ -8,14 +8,15 @@ public class GHBranchSync extends GitHubInteractiveObject { /** - * The base branch. + * Create default GHBranchSync instance */ - private String baseBranch; + public GHBranchSync() { + } /** - * The merge type. + * The Repository that this branch is in. */ - private String mergeType; + private GHRepository owner; /** * The message. @@ -23,51 +24,50 @@ public class GHBranchSync extends GitHubInteractiveObject { private String message; /** - * The Repository that this branch is in. + * The merge type. */ - private GHRepository owner; + private String mergeType; /** - * Create default GHBranchSync instance + * The base branch. */ - public GHBranchSync() { - } + private String baseBranch; /** - * Gets base branch. + * Gets owner. * - * @return the base branch + * @return the repository that this branch is in. */ - public String getBaseBranch() { - return baseBranch; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getOwner() { + return owner; } /** - * Gets merge type. + * Gets message. * - * @return the merge type + * @return the message */ - public String getMergeType() { - return mergeType; + public String getMessage() { + return message; } /** - * Gets message. + * Gets merge type. * - * @return the message + * @return the merge type */ - public String getMessage() { - return message; + public String getMergeType() { + return mergeType; } /** - * Gets owner. + * Gets base branch. * - * @return the repository that this branch is in. + * @return the base branch */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return owner; + public String getBaseBranch() { + return baseBranch; } /** diff --git a/src/main/java/org/kohsuke/github/GHCheckRun.java b/src/main/java/org/kohsuke/github/GHCheckRun.java index 2c776af8d7..cb12173ae4 100644 --- a/src/main/java/org/kohsuke/github/GHCheckRun.java +++ b/src/main/java/org/kohsuke/github/GHCheckRun.java @@ -1,14 +1,12 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JsonProperty; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.kohsuke.github.internal.EnumUtils; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -26,42 +24,88 @@ public class GHCheckRun extends GHObject { /** - * The Enum AnnotationLevel. + * Create default GHCheckRun instance */ - public static enum AnnotationLevel { + public GHCheckRun() { + } - /** The failure. */ - FAILURE, - /** The notice. */ - NOTICE, - /** The warning. */ - WARNING + /** The owner. */ + @JsonProperty("repository") + GHRepository owner; + + private String status; + private String conclusion; + private String name; + private String headSha; + private String nodeId; + private String externalId; + private String startedAt; + private String completedAt; + private String htmlUrl; + private String detailsUrl; + private Output output; + private GHApp app; + private GHPullRequest[] pullRequests = new GHPullRequest[0]; + private GHCheckSuite checkSuite; + + /** + * Wrap. + * + * @param owner + * the owner + * @return the GH check run + */ + GHCheckRun wrap(GHRepository owner) { + this.owner = owner; + wrap(owner.root()); + return this; } /** - * Final conclusion of the check. + * Wrap. * - * From Check Run - * Parameters - conclusion. + * @param root + * the root + * @return the GH check run */ - public static enum Conclusion { + GHCheckRun wrap(GitHub root) { + if (owner != null) { + for (GHPullRequest singlePull : pullRequests) { + singlePull.wrap(owner); + } + } + if (checkSuite != null) { + if (owner != null) { + checkSuite.wrap(owner); + } else { + checkSuite.wrap(root); + } + } - /** The action required. */ - ACTION_REQUIRED, - /** The cancelled. */ - CANCELLED, - /** The failure. */ - FAILURE, - /** The neutral. */ - NEUTRAL, - /** The skipped. */ - SKIPPED, - /** The stale. */ - STALE, - /** The success. */ - SUCCESS, - /** The timed out. */ - TIMED_OUT, + return this; + } + + /** + * Gets status of the check run. + * + * @return Status of the check run + * @see Status + */ + public Status getStatus() { + return Status.from(status); + } + + /** + * The Enum Status. + */ + public static enum Status { + + /** The queued. */ + QUEUED, + /** The in progress. */ + IN_PROGRESS, + /** The completed. */ + COMPLETED, /** The unknown. */ UNKNOWN; @@ -70,10 +114,10 @@ public static enum Conclusion { * * @param value * the value - * @return the conclusion + * @return the status */ - public static Conclusion from(String value) { - return EnumUtils.getNullableEnumOrDefault(Conclusion.class, value, Conclusion.UNKNOWN); + public static Status from(String value) { + return EnumUtils.getNullableEnumOrDefault(Status.class, value, Status.UNKNOWN); } /** @@ -88,80 +132,39 @@ public String toString() { } /** - * Represents an output in a check run to include summary and other results. + * Gets conclusion of a completed check run. * - * @see documentation + * @return Status of the check run + * @see Conclusion */ - public static class Output { - - private int annotationsCount; - - private String annotationsUrl; - private String summary; - private String text; - private String title; - /** - * Create default Output instance - */ - public Output() { - } - - /** - * Gets the annotation count of a check run. - * - * @return annotation count of a check run - */ - public int getAnnotationsCount() { - return annotationsCount; - } - - /** - * Gets the URL of annotations. - * - * @return URL of annotations - */ - public URL getAnnotationsUrl() { - return GitHubClient.parseURL(annotationsUrl); - } - - /** - * Gets the summary of the check run, note that it supports Markdown. - * - * @return summary of check run - */ - public String getSummary() { - return summary; - } - - /** - * Gets the details of the check run, note that it supports Markdown. - * - * @return Details of the check run - */ - public String getText() { - return text; - } - - /** - * Gets the title of check run. - * - * @return title of check run - */ - public String getTitle() { - return title; - } + public Conclusion getConclusion() { + return Conclusion.from(conclusion); } + /** - * The Enum Status. + * Final conclusion of the check. + * + * From Check Run + * Parameters - conclusion. */ - public static enum Status { + public static enum Conclusion { - /** The completed. */ - COMPLETED, - /** The in progress. */ - IN_PROGRESS, - /** The queued. */ - QUEUED, + /** The action required. */ + ACTION_REQUIRED, + /** The cancelled. */ + CANCELLED, + /** The failure. */ + FAILURE, + /** The neutral. */ + NEUTRAL, + /** The success. */ + SUCCESS, + /** The skipped. */ + SKIPPED, + /** The stale. */ + STALE, + /** The timed out. */ + TIMED_OUT, /** The unknown. */ UNKNOWN; @@ -170,10 +173,10 @@ public static enum Status { * * @param value * the value - * @return the status + * @return the conclusion */ - public static Status from(String value) { - return EnumUtils.getNullableEnumOrDefault(Status.class, value, Status.UNKNOWN); + public static Conclusion from(String value) { + return EnumUtils.getNullableEnumOrDefault(Conclusion.class, value, Conclusion.UNKNOWN); } /** @@ -186,80 +189,61 @@ public String toString() { return name().toLowerCase(Locale.ROOT); } } - private GHApp app; - private GHCheckSuite checkSuite; - private String completedAt; - private String conclusion; - private String detailsUrl; - private String externalId; - private String headSha; - private String htmlUrl; - private String name; - private String nodeId; - private Output output; - private GHPullRequest[] pullRequests = new GHPullRequest[0]; - - private String startedAt; - - private String status; - - /** The owner. */ - @JsonProperty("repository") - GHRepository owner; - - /** - * Create default GHCheckRun instance - */ - public GHCheckRun() { - } /** - * Gets the GitHub app this check run belongs to, included in response. + * Gets the custom name of this check run. * - * @return GitHub App + * @return Name of the check run */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHApp getApp() { - return app; + public String getName() { + return name; } /** - * Gets the check suite this check run belongs to. + * Gets the HEAD SHA. * - * @return Check suite + * @return sha for the HEAD commit */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHCheckSuite getCheckSuite() { - return checkSuite; + public String getHeadSha() { + return headSha; } /** - * Gets the completed time of the check run in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. + * Gets the pull requests participated in this check run. * - * @return Timestamp of the completed time + * Note this field is only populated for events. When getting a {@link GHCheckRun} outside of an event, this is + * always empty. + * + * @return the list of {@link GHPullRequest}s for this check run. Only populated for events. + * @throws IOException + * the io exception */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCompletedAt() { - return GitHubClient.parseInstant(completedAt); + public List getPullRequests() throws IOException { + for (GHPullRequest singlePull : pullRequests) { + // Only refresh if we haven't do so before + singlePull.refresh(singlePull.getTitle()); + } + return Collections.unmodifiableList(Arrays.asList(pullRequests)); } /** - * Gets conclusion of a completed check run. + * Gets the HTML URL: https://github.com/[owner]/[repo-name]/runs/[check-run-id], usually an GitHub Action page of + * the check run. * - * @return Status of the check run - * @see Conclusion + * @return HTML URL */ - public Conclusion getConclusion() { - return Conclusion.from(conclusion); + public URL getHtmlUrl() { + return GitHubClient.parseURL(htmlUrl); } /** - * Gets the details URL from which to find full details of the check run on the integrator's site. + * Gets the global node id to access most objects in GitHub. * - * @return Details URL + * @return Global node id + * @see documentation */ - public URL getDetailsUrl() { - return GitHubClient.parseURL(detailsUrl); + public String getNodeId() { + return nodeId; } /** @@ -272,41 +256,50 @@ public String getExternalId() { } /** - * Gets the HEAD SHA. + * Gets the details URL from which to find full details of the check run on the integrator's site. * - * @return sha for the HEAD commit + * @return Details URL */ - public String getHeadSha() { - return headSha; + public URL getDetailsUrl() { + return GitHubClient.parseURL(detailsUrl); } /** - * Gets the HTML URL: https://github.com/[owner]/[repo-name]/runs/[check-run-id], usually an GitHub Action page of - * the check run. + * Gets the start time of the check run in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. * - * @return HTML URL + * @return Timestamp of the start time */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public Date getStartedAt() { + return GitHubClient.parseDate(startedAt); } /** - * Gets the custom name of this check run. + * Gets the completed time of the check run in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. * - * @return Name of the check run + * @return Timestamp of the completed time */ - public String getName() { - return name; + public Date getCompletedAt() { + return GitHubClient.parseDate(completedAt); } /** - * Gets the global node id to access most objects in GitHub. + * Gets the GitHub app this check run belongs to, included in response. * - * @return Global node id - * @see documentation + * @return GitHub App */ - public String getNodeId() { - return nodeId; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHApp getApp() { + return app; + } + + /** + * Gets the check suite this check run belongs to. + * + * @return Check suite + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHCheckSuite getCheckSuite() { + return checkSuite; } /** @@ -320,41 +313,81 @@ public Output getOutput() { } /** - * Gets the pull requests participated in this check run. - * - * Note this field is only populated for events. When getting a {@link GHCheckRun} outside of an event, this is - * always empty. + * Represents an output in a check run to include summary and other results. * - * @return the list of {@link GHPullRequest}s for this check run. Only populated for events. - * @throws IOException - * the io exception + * @see documentation */ - public List getPullRequests() throws IOException { - for (GHPullRequest singlePull : pullRequests) { - // Only refresh if we haven't do so before - singlePull.refresh(singlePull.getTitle()); + public static class Output { + + /** + * Create default Output instance + */ + public Output() { } - return Collections.unmodifiableList(Arrays.asList(pullRequests)); - } - /** - * Gets the start time of the check run in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ. - * - * @return Timestamp of the start time - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getStartedAt() { - return GitHubClient.parseInstant(startedAt); + private String title; + private String summary; + private String text; + private int annotationsCount; + private String annotationsUrl; + + /** + * Gets the title of check run. + * + * @return title of check run + */ + public String getTitle() { + return title; + } + + /** + * Gets the summary of the check run, note that it supports Markdown. + * + * @return summary of check run + */ + public String getSummary() { + return summary; + } + + /** + * Gets the details of the check run, note that it supports Markdown. + * + * @return Details of the check run + */ + public String getText() { + return text; + } + + /** + * Gets the annotation count of a check run. + * + * @return annotation count of a check run + */ + public int getAnnotationsCount() { + return annotationsCount; + } + + /** + * Gets the URL of annotations. + * + * @return URL of annotations + */ + public URL getAnnotationsUrl() { + return GitHubClient.parseURL(annotationsUrl); + } } /** - * Gets status of the check run. - * - * @return Status of the check run - * @see Status + * The Enum AnnotationLevel. */ - public Status getStatus() { - return Status.from(status); + public static enum AnnotationLevel { + + /** The notice. */ + NOTICE, + /** The warning. */ + WARNING, + /** The failure. */ + FAILURE } /** @@ -366,41 +399,4 @@ public Status getStatus() { return new GHCheckRunBuilder(owner, getId()); } - /** - * Wrap. - * - * @param owner - * the owner - * @return the GH check run - */ - GHCheckRun wrap(GHRepository owner) { - this.owner = owner; - wrap(owner.root()); - return this; - } - - /** - * Wrap. - * - * @param root - * the root - * @return the GH check run - */ - GHCheckRun wrap(GitHub root) { - if (owner != null) { - for (GHPullRequest singlePull : pullRequests) { - singlePull.wrap(owner); - } - } - if (checkSuite != null) { - if (owner != null) { - checkSuite.wrap(owner); - } else { - checkSuite.wrap(root); - } - } - - return this; - } - } diff --git a/src/main/java/org/kohsuke/github/GHCheckRunBuilder.java b/src/main/java/org/kohsuke/github/GHCheckRunBuilder.java index 0dcff092ba..eefe6d0235 100644 --- a/src/main/java/org/kohsuke/github/GHCheckRunBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCheckRunBuilder.java @@ -30,7 +30,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; -import java.time.Instant; import java.util.Collections; import java.util.Date; import java.util.LinkedList; @@ -50,268 +49,13 @@ @SuppressFBWarnings(value = "URF_UNREAD_FIELD", justification = "Jackson serializes these even without a getter") public final class GHCheckRunBuilder { - /** - * The Class Action. - * - * @see documentation - */ - @JsonInclude(JsonInclude.Include.NON_NULL) - public static final class Action { - - private final String description; - private final String identifier; - private final String label; - - /** - * Instantiates a new action. - * - * @param label - * the label - * @param description - * the description - * @param identifier - * the identifier - */ - public Action(@NonNull String label, @NonNull String description, @NonNull String identifier) { - this.label = label; - this.description = description; - this.identifier = identifier; - } - - } - - /** - * The Class Annotation. - * - * @see documentation - */ - @JsonInclude(JsonInclude.Include.NON_NULL) - public static final class Annotation { - - private final String annotationLevel; - private Integer endColumn; - private final int endLine; - private final String message; - private final String path; - private String rawDetails; - private Integer startColumn; - private final int startLine; - private String title; - - /** - * Instantiates a new annotation. - * - * @param path - * the path - * @param line - * the line - * @param annotationLevel - * the annotation level - * @param message - * the message - */ - public Annotation(@NonNull String path, - int line, - @NonNull GHCheckRun.AnnotationLevel annotationLevel, - @NonNull String message) { - this(path, line, line, annotationLevel, message); - } - - /** - * Instantiates a new annotation. - * - * @param path - * the path - * @param startLine - * the start line - * @param endLine - * the end line - * @param annotationLevel - * the annotation level - * @param message - * the message - */ - public Annotation(@NonNull String path, - int startLine, - int endLine, - @NonNull GHCheckRun.AnnotationLevel annotationLevel, - @NonNull String message) { - this.path = path; - this.startLine = startLine; - this.endLine = endLine; - this.annotationLevel = annotationLevel.toString().toLowerCase(Locale.ROOT); - this.message = message; - } - - /** - * With end column. - * - * @param endColumn - * the end column - * @return the annotation - */ - public @NonNull Annotation withEndColumn(@CheckForNull Integer endColumn) { - this.endColumn = endColumn; - return this; - } - - /** - * With raw details. - * - * @param rawDetails - * the raw details - * @return the annotation - */ - public @NonNull Annotation withRawDetails(@CheckForNull String rawDetails) { - this.rawDetails = rawDetails; - return this; - } - - /** - * With start column. - * - * @param startColumn - * the start column - * @return the annotation - */ - public @NonNull Annotation withStartColumn(@CheckForNull Integer startColumn) { - this.startColumn = startColumn; - return this; - } - - /** - * With title. - * - * @param title - * the title - * @return the annotation - */ - public @NonNull Annotation withTitle(@CheckForNull String title) { - this.title = title; - return this; - } - - } - /** - * The Class Image. - * - * @see documentation - */ - @JsonInclude(JsonInclude.Include.NON_NULL) - public static final class Image { - - private final String alt; - private String caption; - private final String imageUrl; - - /** - * Instantiates a new image. - * - * @param alt - * the alt - * @param imageURL - * the image URL - */ - public Image(@NonNull String alt, @NonNull String imageURL) { - this.alt = alt; - this.imageUrl = imageURL; - } - - /** - * With caption. - * - * @param caption - * the caption - * @return the image - */ - public @NonNull Image withCaption(@CheckForNull String caption) { - this.caption = caption; - return this; - } - - } - /** - * The Class Output. - * - * @see documentation - */ - @JsonInclude(JsonInclude.Include.NON_NULL) - public static final class Output { - - private List annotations; - private List images; - private final String summary; - private String text; - private final String title; - - /** - * Instantiates a new output. - * - * @param title - * the title - * @param summary - * the summary - */ - public Output(@NonNull String title, @NonNull String summary) { - this.title = title; - this.summary = summary; - } - - /** - * Adds the. - * - * @param annotation - * the annotation - * @return the output - */ - public @NonNull Output add(@NonNull Annotation annotation) { - if (annotations == null) { - annotations = new LinkedList<>(); - } - annotations.add(annotation); - return this; - } - - /** - * Adds the. - * - * @param image - * the image - * @return the output - */ - public @NonNull Output add(@NonNull Image image) { - if (images == null) { - images = new LinkedList<>(); - } - images.add(image); - return this; - } - - /** - * With text. - * - * @param text - * the text - * @return the output - */ - public @NonNull Output withText(@CheckForNull String text) { - this.text = text; - return this; - } - - } - - private static final int MAX_ANNOTATIONS = 50; - - private List actions; - - private Output output; - /** The repo. */ protected final GHRepository repo; /** The requester. */ protected final Requester requester; + private Output output; + private List actions; private GHCheckRunBuilder(GHRepository repo, Requester requester) { this.repo = repo; @@ -352,17 +96,100 @@ private GHCheckRunBuilder(GHRepository repo, Requester requester) { } /** - * Adds the. + * With name. * - * @param action - * the action + * @param name + * the name + * @param oldName + * the old name * @return the GH check run builder */ - public @NonNull GHCheckRunBuilder add(@NonNull Action action) { - if (actions == null) { - actions = new LinkedList<>(); + public @NonNull GHCheckRunBuilder withName(@CheckForNull String name, String oldName) { + if (oldName == null) { + throw new GHException("Can not update uncreated check run"); + } + requester.with("name", name); + return this; + } + + /** + * With details URL. + * + * @param detailsURL + * the details URL + * @return the GH check run builder + */ + public @NonNull GHCheckRunBuilder withDetailsURL(@CheckForNull String detailsURL) { + requester.with("details_url", detailsURL); + return this; + } + + /** + * With external ID. + * + * @param externalID + * the external ID + * @return the GH check run builder + */ + public @NonNull GHCheckRunBuilder withExternalID(@CheckForNull String externalID) { + requester.with("external_id", externalID); + return this; + } + + /** + * With status. + * + * @param status + * the status + * @return the GH check run builder + */ + public @NonNull GHCheckRunBuilder withStatus(@CheckForNull GHCheckRun.Status status) { + if (status != null) { + // Do *not* use the overload taking Enum, as that s/_/-/g which would be wrong here. + requester.with("status", status.toString().toLowerCase(Locale.ROOT)); + } + return this; + } + + /** + * With conclusion. + * + * @param conclusion + * the conclusion + * @return the GH check run builder + */ + public @NonNull GHCheckRunBuilder withConclusion(@CheckForNull GHCheckRun.Conclusion conclusion) { + if (conclusion != null) { + requester.with("conclusion", conclusion.toString().toLowerCase(Locale.ROOT)); + } + return this; + } + + /** + * With started at. + * + * @param startedAt + * the started at + * @return the GH check run builder + */ + public @NonNull GHCheckRunBuilder withStartedAt(@CheckForNull Date startedAt) { + if (startedAt != null) { + requester.with("started_at", GitHubClient.printDate(startedAt)); + } + return this; + } + + /** + * With completed at. + * + * @param completedAt + * the completed at + * @return the GH check run builder + */ + public @NonNull GHCheckRunBuilder withCompletedAt(@CheckForNull Date completedAt) { + if (completedAt != null) { + requester.with("completed_at", GitHubClient.printDate(completedAt)); } - actions.add(action); return this; } @@ -381,6 +208,22 @@ private GHCheckRunBuilder(GHRepository repo, Requester requester) { return this; } + /** + * Adds the. + * + * @param action + * the action + * @return the GH check run builder + */ + public @NonNull GHCheckRunBuilder add(@NonNull Action action) { + if (actions == null) { + actions = new LinkedList<>(); + } + actions.add(action); + return this; + } + + private static final int MAX_ANNOTATIONS = 50; /** * Actually creates the check run. (If more than fifty annotations were requested, this is done in batches.) * @@ -414,126 +257,256 @@ private GHCheckRunBuilder(GHRepository repo, Requester requester) { } /** - * With completed at. + * The Class Output. * - * @param completedAt - * the completed at - * @return the GH check run builder - * @deprecated Use {@link #withCompletedAt(Instant)} + * @see documentation */ - @Deprecated - public @NonNull GHCheckRunBuilder withCompletedAt(@CheckForNull Date completedAt) { - return withCompletedAt(GitHubClient.toInstantOrNull(completedAt)); - } + @JsonInclude(JsonInclude.Include.NON_NULL) + public static final class Output { - /** - * With completed at. - * - * @param completedAt - * the completed at - * @return the GH check run builder - */ - public @NonNull GHCheckRunBuilder withCompletedAt(@CheckForNull Instant completedAt) { - if (completedAt != null) { - requester.with("completed_at", GitHubClient.printInstant(completedAt)); + private final String title; + private final String summary; + private String text; + private List annotations; + private List images; + + /** + * Instantiates a new output. + * + * @param title + * the title + * @param summary + * the summary + */ + public Output(@NonNull String title, @NonNull String summary) { + this.title = title; + this.summary = summary; } - return this; - } - /** - * With conclusion. - * - * @param conclusion - * the conclusion - * @return the GH check run builder - */ - public @NonNull GHCheckRunBuilder withConclusion(@CheckForNull GHCheckRun.Conclusion conclusion) { - if (conclusion != null) { - requester.with("conclusion", conclusion.toString().toLowerCase(Locale.ROOT)); + /** + * With text. + * + * @param text + * the text + * @return the output + */ + public @NonNull Output withText(@CheckForNull String text) { + this.text = text; + return this; } - return this; - } - /** - * With details URL. - * - * @param detailsURL - * the details URL - * @return the GH check run builder - */ - public @NonNull GHCheckRunBuilder withDetailsURL(@CheckForNull String detailsURL) { - requester.with("details_url", detailsURL); - return this; - } - /** - * With external ID. - * - * @param externalID - * the external ID - * @return the GH check run builder - */ - public @NonNull GHCheckRunBuilder withExternalID(@CheckForNull String externalID) { - requester.with("external_id", externalID); - return this; - } + /** + * Adds the. + * + * @param annotation + * the annotation + * @return the output + */ + public @NonNull Output add(@NonNull Annotation annotation) { + if (annotations == null) { + annotations = new LinkedList<>(); + } + annotations.add(annotation); + return this; + } - /** - * With name. - * - * @param name - * the name - * @param oldName - * the old name - * @return the GH check run builder - */ - public @NonNull GHCheckRunBuilder withName(@CheckForNull String name, String oldName) { - if (oldName == null) { - throw new GHException("Can not update uncreated check run"); + /** + * Adds the. + * + * @param image + * the image + * @return the output + */ + public @NonNull Output add(@NonNull Image image) { + if (images == null) { + images = new LinkedList<>(); + } + images.add(image); + return this; } - requester.with("name", name); - return this; + } /** - * With started at. + * The Class Annotation. * - * @param startedAt - * the started at - * @return the GH check run builder - * @deprecated Use {@link #withStartedAt(Instant)} + * @see documentation */ - @Deprecated - public @NonNull GHCheckRunBuilder withStartedAt(@CheckForNull Date startedAt) { - return withStartedAt(GitHubClient.toInstantOrNull(startedAt)); + @JsonInclude(JsonInclude.Include.NON_NULL) + public static final class Annotation { + + private final String path; + private final int start_line; + private final int end_line; + private final String annotation_level; + private final String message; + private Integer start_column; + private Integer end_column; + private String title; + private String raw_details; + + /** + * Instantiates a new annotation. + * + * @param path + * the path + * @param line + * the line + * @param annotationLevel + * the annotation level + * @param message + * the message + */ + public Annotation(@NonNull String path, + int line, + @NonNull GHCheckRun.AnnotationLevel annotationLevel, + @NonNull String message) { + this(path, line, line, annotationLevel, message); + } + + /** + * Instantiates a new annotation. + * + * @param path + * the path + * @param startLine + * the start line + * @param endLine + * the end line + * @param annotationLevel + * the annotation level + * @param message + * the message + */ + public Annotation(@NonNull String path, + int startLine, + int endLine, + @NonNull GHCheckRun.AnnotationLevel annotationLevel, + @NonNull String message) { + this.path = path; + start_line = startLine; + end_line = endLine; + annotation_level = annotationLevel.toString().toLowerCase(Locale.ROOT); + this.message = message; + } + + /** + * With start column. + * + * @param startColumn + * the start column + * @return the annotation + */ + public @NonNull Annotation withStartColumn(@CheckForNull Integer startColumn) { + start_column = startColumn; + return this; + } + + /** + * With end column. + * + * @param endColumn + * the end column + * @return the annotation + */ + public @NonNull Annotation withEndColumn(@CheckForNull Integer endColumn) { + end_column = endColumn; + return this; + } + + /** + * With title. + * + * @param title + * the title + * @return the annotation + */ + public @NonNull Annotation withTitle(@CheckForNull String title) { + this.title = title; + return this; + } + + /** + * With raw details. + * + * @param rawDetails + * the raw details + * @return the annotation + */ + public @NonNull Annotation withRawDetails(@CheckForNull String rawDetails) { + raw_details = rawDetails; + return this; + } + } /** - * With started at. + * The Class Image. * - * @param startedAt - * the started at - * @return the GH check run builder + * @see documentation */ - public @NonNull GHCheckRunBuilder withStartedAt(@CheckForNull Instant startedAt) { - if (startedAt != null) { - requester.with("started_at", GitHubClient.printInstant(startedAt)); + @JsonInclude(JsonInclude.Include.NON_NULL) + public static final class Image { + + private final String alt; + private final String image_url; + private String caption; + + /** + * Instantiates a new image. + * + * @param alt + * the alt + * @param imageURL + * the image URL + */ + public Image(@NonNull String alt, @NonNull String imageURL) { + this.alt = alt; + image_url = imageURL; } - return this; + + /** + * With caption. + * + * @param caption + * the caption + * @return the image + */ + public @NonNull Image withCaption(@CheckForNull String caption) { + this.caption = caption; + return this; + } + } /** - * With status. + * The Class Action. * - * @param status - * the status - * @return the GH check run builder + * @see documentation */ - public @NonNull GHCheckRunBuilder withStatus(@CheckForNull GHCheckRun.Status status) { - if (status != null) { - // Do *not* use the overload taking Enum, as that s/_/-/g which would be wrong here. - requester.with("status", status.toString().toLowerCase(Locale.ROOT)); + @JsonInclude(JsonInclude.Include.NON_NULL) + public static final class Action { + + private final String label; + private final String description; + private final String identifier; + + /** + * Instantiates a new action. + * + * @param label + * the label + * @param description + * the description + * @param identifier + * the identifier + */ + public Action(@NonNull String label, @NonNull String description, @NonNull String identifier) { + this.label = label; + this.description = description; + this.identifier = identifier; } - return this; + } } diff --git a/src/main/java/org/kohsuke/github/GHCheckRunsPage.java b/src/main/java/org/kohsuke/github/GHCheckRunsPage.java index d0b5d012f2..2caf0a711f 100644 --- a/src/main/java/org/kohsuke/github/GHCheckRunsPage.java +++ b/src/main/java/org/kohsuke/github/GHCheckRunsPage.java @@ -9,8 +9,8 @@ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") class GHCheckRunsPage { - private GHCheckRun[] checkRuns; - private int totalCount; + private int total_count; + private GHCheckRun[] check_runs; /** * Gets the total count. @@ -18,7 +18,7 @@ class GHCheckRunsPage { * @return the total count */ public int getTotalCount() { - return totalCount; + return total_count; } /** @@ -29,9 +29,9 @@ public int getTotalCount() { * @return the check runs */ GHCheckRun[] getCheckRuns(GHRepository owner) { - for (GHCheckRun checkRun : checkRuns) { - checkRun.wrap(owner); + for (GHCheckRun check_run : check_runs) { + check_run.wrap(owner); } - return checkRuns; + return check_runs; } } diff --git a/src/main/java/org/kohsuke/github/GHCheckSuite.java b/src/main/java/org/kohsuke/github/GHCheckSuite.java index 0ada44e82b..8c9dea61f7 100644 --- a/src/main/java/org/kohsuke/github/GHCheckSuite.java +++ b/src/main/java/org/kohsuke/github/GHCheckSuite.java @@ -1,12 +1,10 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JsonProperty; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -23,137 +21,103 @@ public class GHCheckSuite extends GHObject { /** - * The Class HeadCommit. + * Create default GHCheckSuite instance */ - public static class HeadCommit extends GitHubBridgeAdapterObject { - - private GitUser author; - - private GitUser committer; - private String id; - private String message; - private String timestamp; - private String treeId; - /** - * Create default HeadCommit instance - */ - public HeadCommit() { - } - - /** - * Gets author. - * - * @return the author - */ - public GitUser getAuthor() { - return author; - } - - /** - * Gets committer. - * - * @return the committer - */ - public GitUser getCommitter() { - return committer; - } - - /** - * Gets id of the commit, used by {@link GHCheckSuite} when a {@link GHEvent#CHECK_SUITE} comes. - * - * @return id of the commit - */ - public String getId() { - return id; - } - - /** - * Gets message. - * - * @return commit message. - */ - public String getMessage() { - return message; - } - - /** - * Gets timestamp of the commit. - * - * @return timestamp of the commit - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getTimestamp() { - return GitHubClient.parseInstant(timestamp); - } - - /** - * Gets id of the tree. - * - * @return id of the tree - */ - public String getTreeId() { - return treeId; - } + public GHCheckSuite() { } - private String after; + /** The owner. */ + @JsonProperty("repository") + GHRepository owner; - private GHApp app; - private String before; - private String checkRunsUrl; - private String conclusion; + private String nodeId; private String headBranch; - private HeadCommit headCommit; private String headSha; + private String status; + private String conclusion; + private String before; + private String after; private int latestCheckRunsCount; - private String nodeId; + private String checkRunsUrl; + private HeadCommit headCommit; + private GHApp app; private GHPullRequest[] pullRequests; - private String status; - /** The owner. */ - @JsonProperty("repository") - GHRepository owner; /** - * Create default GHCheckSuite instance + * Wrap. + * + * @param owner + * the owner + * @return the GH check suite */ - public GHCheckSuite() { + GHCheckSuite wrap(GHRepository owner) { + this.owner = owner; + this.wrap(owner.root()); + return this; } /** - * The SHA of the most recent commit on ref after the push. + * Wrap. * - * @return sha of a commit + * @param root + * the root + * @return the GH check suite */ - public String getAfter() { - return after; + GHCheckSuite wrap(GitHub root) { + if (owner != null) { + if (pullRequests != null && pullRequests.length != 0) { + for (GHPullRequest singlePull : pullRequests) { + singlePull.wrap(owner); + } + } + } + return this; } /** - * Gets the GitHub app this check suite belongs to, included in response. + * Wrap. * - * @return GitHub App + * @return the GH pull request[] */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHApp getApp() { - return app; + GHPullRequest[] wrap() { + return pullRequests; } /** - * The SHA of the most recent commit on ref before the push. + * Gets the global node id to access most objects in GitHub. * - * @return sha of a commit + * @return global node id + * @see documentation */ - public String getBefore() { - return before; + public String getNodeId() { + return nodeId; } /** - * The url used to list all the check runs belonged to this suite. + * The head branch name the changes are on. * - * @return url containing all check runs + * @return head branch name */ - public URL getCheckRunsUrl() { - return GitHubClient.parseURL(checkRunsUrl); + public String getHeadBranch() { + return headBranch; + } + + /** + * Gets the HEAD SHA. + * + * @return sha for the HEAD commit + */ + public String getHeadSha() { + return headSha; + } + + /** + * Gets status of the check suite. It can be one of request, in_progress, or completed. + * + * @return status of the check suite + */ + public String getStatus() { + return status; } /** @@ -168,49 +132,58 @@ public String getConclusion() { } /** - * The head branch name the changes are on. + * The SHA of the most recent commit on ref before the push. * - * @return head branch name + * @return sha of a commit */ - public String getHeadBranch() { - return headBranch; + public String getBefore() { + return before; } /** - * The commit of current head. + * The SHA of the most recent commit on ref after the push. * - * @return head commit + * @return sha of a commit */ - public HeadCommit getHeadCommit() { - return headCommit; + public String getAfter() { + return after; } /** - * Gets the HEAD SHA. + * The quantity of check runs that had run as part of the latest push. * - * @return sha for the HEAD commit + * @return sha of the most recent commit */ - public String getHeadSha() { - return headSha; + public int getLatestCheckRunsCount() { + return latestCheckRunsCount; } /** - * The quantity of check runs that had run as part of the latest push. + * The url used to list all the check runs belonged to this suite. * - * @return sha of the most recent commit + * @return url containing all check runs */ - public int getLatestCheckRunsCount() { - return latestCheckRunsCount; + public URL getCheckRunsUrl() { + return GitHubClient.parseURL(checkRunsUrl); } /** - * Gets the global node id to access most objects in GitHub. + * The commit of current head. * - * @return global node id - * @see documentation + * @return head commit */ - public String getNodeId() { - return nodeId; + public HeadCommit getHeadCommit() { + return headCommit; + } + + /** + * Gets the GitHub app this check suite belongs to, included in response. + * + * @return GitHub App + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHApp getApp() { + return app; } /** @@ -235,51 +208,75 @@ public List getPullRequests() throws IOException { } /** - * Gets status of the check suite. It can be one of request, in_progress, or completed. - * - * @return status of the check suite + * The Class HeadCommit. */ - public String getStatus() { - return status; - } + public static class HeadCommit { - /** - * Wrap. - * - * @return the GH pull request[] - */ - GHPullRequest[] wrap() { - return pullRequests; - } + /** + * Create default HeadCommit instance + */ + public HeadCommit() { + } - /** - * Wrap. - * - * @param owner - * the owner - * @return the GH check suite - */ - GHCheckSuite wrap(GHRepository owner) { - this.owner = owner; - this.wrap(owner.root()); - return this; - } + private String id; + private String treeId; + private String message; + private String timestamp; + private GitUser author; + private GitUser committer; - /** - * Wrap. - * - * @param root - * the root - * @return the GH check suite - */ - GHCheckSuite wrap(GitHub root) { - if (owner != null) { - if (pullRequests != null && pullRequests.length != 0) { - for (GHPullRequest singlePull : pullRequests) { - singlePull.wrap(owner); - } - } + /** + * Gets id of the commit, used by {@link GHCheckSuite} when a {@link GHEvent#CHECK_SUITE} comes. + * + * @return id of the commit + */ + public String getId() { + return id; + } + + /** + * Gets id of the tree. + * + * @return id of the tree + */ + public String getTreeId() { + return treeId; + } + + /** + * Gets message. + * + * @return commit message. + */ + public String getMessage() { + return message; + } + + /** + * Gets timestamp of the commit. + * + * @return timestamp of the commit + */ + public Date getTimestamp() { + return GitHubClient.parseDate(timestamp); + } + + /** + * Gets author. + * + * @return the author + */ + public GitUser getAuthor() { + return author; + } + + /** + * Gets committer. + * + * @return the committer + */ + public GitUser getCommitter() { + return committer; } - return this; } } diff --git a/src/main/java/org/kohsuke/github/GHCodeownersError.java b/src/main/java/org/kohsuke/github/GHCodeownersError.java index b090a1673b..49654263b1 100644 --- a/src/main/java/org/kohsuke/github/GHCodeownersError.java +++ b/src/main/java/org/kohsuke/github/GHCodeownersError.java @@ -9,14 +9,23 @@ */ public class GHCodeownersError { - private String kind, source, suggestion, message, path; + /** + * Create default GHCodeownersError instance + */ + public GHCodeownersError() { + } private int line, column; + private String kind, source, suggestion, message, path; + /** - * Create default GHCodeownersError instance + * Gets line. + * + * @return the line */ - public GHCodeownersError() { + public int getLine() { + return line; } /** @@ -38,12 +47,21 @@ public String getKind() { } /** - * Gets line. + * Gets source. * - * @return the line + * @return the source */ - public int getLine() { - return line; + public String getSource() { + return source; + } + + /** + * Gets suggestion. + * + * @return the suggestion + */ + public String getSuggestion() { + return suggestion; } /** @@ -63,22 +81,4 @@ public String getMessage() { public String getPath() { return path; } - - /** - * Gets source. - * - * @return the source - */ - public String getSource() { - return source; - } - - /** - * Gets suggestion. - * - * @return the suggestion - */ - public String getSuggestion() { - return suggestion; - } } diff --git a/src/main/java/org/kohsuke/github/GHCommentAuthorAssociation.java b/src/main/java/org/kohsuke/github/GHCommentAuthorAssociation.java index 011016f504..b00905ab8f 100644 --- a/src/main/java/org/kohsuke/github/GHCommentAuthorAssociation.java +++ b/src/main/java/org/kohsuke/github/GHCommentAuthorAssociation.java @@ -38,9 +38,5 @@ public enum GHCommentAuthorAssociation { /** * Author is the owner of the repository. */ - OWNER, - /** - * Author association is not recognized. - */ - UNKNOWN + OWNER } diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index 1edf0503d3..c1d987483a 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -1,11 +1,9 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.AbstractList; import java.util.ArrayList; import java.util.Collections; @@ -23,61 +21,109 @@ @SuppressFBWarnings(value = { "NP_UNWRITTEN_FIELD", "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") public class GHCommit { + private GHRepository owner; + + private ShortInfo commit; + /** - * A file that was modified. + * Short summary of this commit. */ - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "It's being initialized by JSON deserialization") - public static class File { - - /** The deletions. */ - int changes, additions, deletions; + @SuppressFBWarnings( + value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", + "UWF_UNWRITTEN_FIELD" }, + justification = "JSON API") + public static class ShortInfo extends GitCommit { - /** The previous filename. */ - String filename, previousFilename; + private int comment_count = -1; - /** The patch. */ - String rawUrl, blobUrl, sha, patch; + /** + * Gets comment count. + * + * @return the comment count + * @throws GHException + * the GH exception + */ + public int getCommentCount() throws GHException { + if (comment_count < 0) { + throw new GHException("Not available on this endpoint."); + } + return comment_count; + } - /** The status. */ - String status; + /** + * Creates instance of {@link GHCommit.ShortInfo}. + */ + public ShortInfo() { + // Empty constructor required for Jackson binding + }; /** - * Create default File instance + * Instantiates a new short info. + * + * @param commit + * the commit */ - public File() { + ShortInfo(GitCommit commit) { + // Inherited copy constructor, used for bridge method from {@link GitCommit}, + // which is used in {@link GHContentUpdateResponse}) to {@link GHCommit}. + super(commit); } /** - * Gets blob url. + * Gets the parent SHA 1 s. * - * @return URL like - * 'https://github.com/jenkinsci/jenkins/blob/1182e2ebb1734d0653142bd422ad33c21437f7cf/core/pom.xml' - * that resolves to the HTML page that describes this file. + * @return the parent SHA 1 s */ - public URL getBlobUrl() { - return GitHubClient.parseURL(blobUrl); + @Override + public List getParentSHA1s() { + List shortInfoParents = super.getParentSHA1s(); + if (shortInfoParents == null) { + throw new GHException("Not available on this endpoint. Try calling getParentSHA1s from outer class."); + } + return shortInfoParents; } + } + + /** + * The type Stats. + */ + public static class Stats { + /** - * Gets file name. - * - * @return Full path in the repository. + * Create default Stats instance */ - @SuppressFBWarnings(value = "NM_CONFUSING", - justification = "It's a part of the library's API and cannot be renamed") - public String getFileName() { - return filename; + public Stats() { } + /** The deletions. */ + int total, additions, deletions; + } + + /** + * A file that was modified. + */ + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "It's being initialized by JSON deserialization") + public static class File { + /** - * Gets lines added. - * - * @return Number of lines added. + * Create default File instance */ - public int getLinesAdded() { - return additions; + public File() { } + /** The status. */ + String status; + + /** The deletions. */ + int changes, additions, deletions; + + /** The patch. */ + String raw_url, blob_url, sha, patch; + + /** The previous filename. */ + String filename, previous_filename; + /** * Gets lines changed. * @@ -87,6 +133,15 @@ public int getLinesChanged() { return changes; } + /** + * Gets lines added. + * + * @return Number of lines added. + */ + public int getLinesAdded() { + return additions; + } + /** * Gets lines deleted. * @@ -97,12 +152,23 @@ public int getLinesDeleted() { } /** - * Gets patch. + * Gets status. * - * @return The actual change. + * @return "modified", "added", or "removed" */ - public String getPatch() { - return patch; + public String getStatus() { + return status; + } + + /** + * Gets file name. + * + * @return Full path in the repository. + */ + @SuppressFBWarnings(value = "NM_CONFUSING", + justification = "It's a part of the library's API and cannot be renamed") + public String getFileName() { + return filename; } /** @@ -111,7 +177,16 @@ public String getPatch() { * @return Previous path, in case file has moved. */ public String getPreviousFilename() { - return previousFilename; + return previous_filename; + } + + /** + * Gets patch. + * + * @return The actual change. + */ + public String getPatch() { + return patch; } /** @@ -122,25 +197,27 @@ public String getPreviousFilename() { * resolves to the actual content of the file. */ public URL getRawUrl() { - return GitHubClient.parseURL(rawUrl); + return GitHubClient.parseURL(raw_url); } /** - * Gets sha. + * Gets blob url. * - * @return [0 -9a-f]{40} SHA1 checksum. + * @return URL like + * 'https://github.com/jenkinsci/jenkins/blob/1182e2ebb1734d0653142bd422ad33c21437f7cf/core/pom.xml' + * that resolves to the HTML page that describes this file. */ - public String getSha() { - return sha; + public URL getBlobUrl() { + return GitHubClient.parseURL(blob_url); } /** - * Gets status. + * Gets sha. * - * @return "modified", "added", or "removed" + * @return [0 -9a-f]{40} SHA1 checksum. */ - public String getStatus() { - return status; + public String getSha() { + return sha; } } @@ -149,93 +226,18 @@ public String getStatus() { */ public static class Parent { - /** The sha. */ - String sha; - - /** The url. */ - @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") - String url; - /** * Create default Parent instance */ public Parent() { } - } - /** - * Short summary of this commit. - */ - @SuppressFBWarnings( - value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", - "UWF_UNWRITTEN_FIELD" }, - justification = "JSON API") - public static class ShortInfo extends GitCommit { - - private int commentCount = -1; - - /** - * Creates instance of {@link GHCommit.ShortInfo}. - */ - public ShortInfo() { - // Empty constructor required for Jackson binding - } - - /** - * Instantiates a new short info. - * - * @param commit - * the commit - */ - ShortInfo(GitCommit commit) { - // Inherited copy constructor, used for bridge method from {@link GitCommit}, - // which is used in {@link GHContentUpdateResponse}) to {@link GHCommit}. - super(commit); - }; - - /** - * Gets comment count. - * - * @return the comment count - * @throws GHException - * the GH exception - */ - public int getCommentCount() throws GHException { - if (commentCount < 0) { - throw new GHException("Not available on this endpoint."); - } - return commentCount; - } - - /** - * Gets the parent SHA 1 s. - * - * @return the parent SHA 1 s - */ - @Override - public List getParentSHA1s() { - List shortInfoParents = super.getParentSHA1s(); - if (shortInfoParents == null) { - throw new GHException("Not available on this endpoint. Try calling getParentSHA1s from outer class."); - } - return shortInfoParents; - } - - } - - /** - * The type Stats. - */ - public static class Stats { - - /** The deletions. */ - int total, additions, deletions; + /** The url. */ + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") + String url; - /** - * Create default Stats instance - */ - public Stats() { - } + /** The sha. */ + String sha; } /** @@ -243,37 +245,33 @@ public Stats() { */ static class User { + /** The gravatar id. */ + // TODO: what if someone who doesn't have an account on GitHub makes a commit? + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") + String url, avatar_url, gravatar_id; + /** The id. */ @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") int id; /** The login. */ String login; - - /** The gravatar id. */ - // TODO: what if someone who doesn't have an account on GitHub makes a commit? - @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") - String url, avatarUrl, gravatarId; } - private ShortInfo commit; - - private GHRepository owner; - - /** The committer. */ - User author, committer; + /** The sha. */ + String url, html_url, sha, message; /** The files. */ List files; - /** The parents. */ - List parents; - /** The stats. */ Stats stats; - /** The sha. */ - String url, htmlUrl, sha, message; + /** The parents. */ + List parents; + + /** The committer. */ + User author, committer; /** * Creates an instance of {@link GHCommit}. @@ -296,7 +294,7 @@ public GHCommit() { commit = shortInfo; owner = commit.getOwner(); - htmlUrl = commit.getHtmlUrl(); + html_url = commit.getHtmlUrl(); sha = commit.getSha(); url = commit.getUrl(); parents = commit.getParents(); @@ -304,119 +302,73 @@ public GHCommit() { } /** - * Create comment gh commit comment. - * - * @param body - * the body - * @return the gh commit comment - * @throws IOException - * the io exception - */ - public GHCommitComment createComment(String body) throws IOException { - return createComment(body, null, null, null); - } - - /** - * Creates a commit comment. - *

- * I'm not sure how path/line/position parameters interact with each other. - * - * @param body - * body of the comment - * @param path - * path of file being commented on - * @param line - * target line for comment - * @param position - * position on line - * @return created GHCommitComment - * @throws IOException - * if comment is not created - */ - public GHCommitComment createComment(String body, String path, Integer line, Integer position) throws IOException { - GHCommitComment r = owner.root() - .createRequest() - .method("POST") - .with("body", body) - .with("path", path) - .with("line", line) - .with("position", position) - .withUrlPath( - String.format("/repos/%s/%s/commits/%s/comments", owner.getOwnerName(), owner.getName(), sha)) - .fetch(GHCommitComment.class); - return r.wrap(owner); - } - - /** - * Gets author. + * Gets commit short info. * - * @return the author + * @return the commit short info * @throws IOException * the io exception */ - public GHUser getAuthor() throws IOException { - populate(); - return resolveUser(author); + public ShortInfo getCommitShortInfo() throws IOException { + if (commit == null) + populate(); + return commit; } /** - * Gets the date the change was authored on. + * Gets owner. * - * @return the date the change was authored on. - * @throws IOException - * if the information was not already fetched and an attempt at fetching the information failed. + * @return the repository that contains the commit. */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getAuthoredDate() throws IOException { - return getCommitShortInfo().getAuthoredDate(); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getOwner() { + return owner; } /** - * Gets check-runs for given sha. + * Gets lines changed. * - * @return check runs for given sha. + * @return the number of lines added + removed. * @throws IOException - * on error + * if the field was not populated and refresh fails */ - public PagedIterable getCheckRuns() throws IOException { - return owner.getCheckRuns(sha); + public int getLinesChanged() throws IOException { + populate(); + return stats.total; } /** - * Gets the date the change was committed on. + * Gets lines added. * - * @return the date the change was committed on. + * @return Number of lines added. * @throws IOException - * if the information was not already fetched and an attempt at fetching the information failed. + * if the field was not populated and refresh fails */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCommitDate() throws IOException { - return getCommitShortInfo().getCommitDate(); + public int getLinesAdded() throws IOException { + populate(); + return stats.additions; } /** - * Gets commit short info. + * Gets lines deleted. * - * @return the commit short info + * @return Number of lines removed. * @throws IOException - * the io exception + * if the field was not populated and refresh fails */ - public ShortInfo getCommitShortInfo() throws IOException { - if (commit == null) - populate(); - return commit; + public int getLinesDeleted() throws IOException { + populate(); + return stats.deletions; } /** - * Gets committer. + * Use this method to walk the tree. * - * @return the committer + * @return a GHTree to walk * @throws IOException - * the io exception + * on error */ - public GHUser getCommitter() throws IOException { - populate(); - return resolveUser(committer); + public GHTree getTree() throws IOException { + return owner.getTree(getCommitShortInfo().getTreeSHA1()); } /** @@ -426,64 +378,42 @@ public GHUser getCommitter() throws IOException { * "https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000" */ public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + return GitHubClient.parseURL(html_url); } /** - * Gets last status. + * Gets sha 1. * - * @return the last status of this commit, which is what gets shown in the UI. - * @throws IOException - * on error + * @return [0 -9a-f]{40} SHA1 checksum. */ - public GHCommitStatus getLastStatus() throws IOException { - return owner.getLastCommitStatus(sha); + public String getSHA1() { + return sha; } /** - * Gets lines added. + * Gets url. * - * @return Number of lines added. - * @throws IOException - * if the field was not populated and refresh fails + * @return API URL of this object. */ - public int getLinesAdded() throws IOException { - populate(); - return stats.additions; + public URL getUrl() { + return GitHubClient.parseURL(url); } /** - * Gets lines changed. + * List of files changed/added/removed in this commit. Uses a paginated list if the files returned by GitHub exceed + * 300 in quantity. * - * @return the number of lines added + removed. + * @return the List of files + * @see Get a + * commit * @throws IOException - * if the field was not populated and refresh fails + * on error */ - public int getLinesChanged() throws IOException { - populate(); - return stats.total; - } + public PagedIterable listFiles() throws IOException { - /** - * Gets lines deleted. - * - * @return Number of lines removed. - * @throws IOException - * if the field was not populated and refresh fails - */ - public int getLinesDeleted() throws IOException { populate(); - return stats.deletions; - } - /** - * Gets owner. - * - * @return the repository that contains the commit. - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return owner; + return new GHCommitFileIterable(owner, sha, files); } /** @@ -523,40 +453,77 @@ public List getParents() throws IOException { } /** - * Gets sha 1. + * Gets author. * - * @return [0 -9a-f]{40} SHA1 checksum. + * @return the author + * @throws IOException + * the io exception */ - public String getSHA1() { - return sha; + public GHUser getAuthor() throws IOException { + populate(); + return resolveUser(author); } /** - * Use this method to walk the tree. + * Gets the date the change was authored on. * - * @return a GHTree to walk + * @return the date the change was authored on. * @throws IOException - * on error + * if the information was not already fetched and an attempt at fetching the information failed. */ - public GHTree getTree() throws IOException { - return owner.getTree(getCommitShortInfo().getTreeSHA1()); + public Date getAuthoredDate() throws IOException { + return getCommitShortInfo().getAuthoredDate(); } /** - * Gets url. + * Gets committer. * - * @return API URL of this object. + * @return the committer + * @throws IOException + * the io exception */ - public URL getUrl() { - return GitHubClient.parseURL(url); + public GHUser getCommitter() throws IOException { + populate(); + return resolveUser(committer); + } + + /** + * Gets the date the change was committed on. + * + * @return the date the change was committed on. + * @throws IOException + * if the information was not already fetched and an attempt at fetching the information failed. + */ + public Date getCommitDate() throws IOException { + return getCommitShortInfo().getCommitDate(); + } + + private GHUser resolveUser(User author) throws IOException { + if (author == null || author.login == null) + return null; + return owner.root().getUser(author.login); + } + + /** + * Retrieves a list of pull requests which contain this commit. + * + * @return {@link PagedIterable} with the pull requests which contain this commit + */ + public PagedIterable listPullRequests() { + return owner.root() + .createRequest() + .withUrlPath(String.format("/repos/%s/%s/commits/%s/pulls", owner.getOwnerName(), owner.getName(), sha)) + .toIterable(GHPullRequest[].class, item -> item.wrapUp(owner)); } /** * Retrieves a list of branches where this commit is the head commit. * * @return {@link PagedIterable} with the branches where the commit is the head commit + * @throws IOException + * the io exception */ - public PagedIterable listBranchesWhereHead() { + public PagedIterable listBranchesWhereHead() throws IOException { return owner.root() .createRequest() .withUrlPath(String.format("/repos/%s/%s/commits/%s/branches-where-head", @@ -576,32 +543,47 @@ public PagedIterable listComments() { } /** - * List of files changed/added/removed in this commit. Uses a paginated list if the files returned by GitHub exceed - * 300 in quantity. + * Creates a commit comment. + *

+ * I'm not sure how path/line/position parameters interact with each other. * - * @return the List of files - * @see Get a - * commit + * @param body + * body of the comment + * @param path + * path of file being commented on + * @param line + * target line for comment + * @param position + * position on line + * @return created GHCommitComment * @throws IOException - * on error + * if comment is not created */ - public PagedIterable listFiles() throws IOException { - - populate(); - - return new GHCommitFileIterable(owner, sha, files); + public GHCommitComment createComment(String body, String path, Integer line, Integer position) throws IOException { + GHCommitComment r = owner.root() + .createRequest() + .method("POST") + .with("body", body) + .with("path", path) + .with("line", line) + .with("position", position) + .withUrlPath( + String.format("/repos/%s/%s/commits/%s/comments", owner.getOwnerName(), owner.getName(), sha)) + .fetch(GHCommitComment.class); + return r.wrap(owner); } /** - * Retrieves a list of pull requests which contain this commit. + * Create comment gh commit comment. * - * @return {@link PagedIterable} with the pull requests which contain this commit + * @param body + * the body + * @return the gh commit comment + * @throws IOException + * the io exception */ - public PagedIterable listPullRequests() { - return owner.root() - .createRequest() - .withUrlPath(String.format("/repos/%s/%s/commits/%s/pulls", owner.getOwnerName(), owner.getName(), sha)) - .toIterable(GHPullRequest[].class, item -> item.wrapUp(owner)); + public GHCommitComment createComment(String body) throws IOException { + return createComment(body, null, null, null); } /** @@ -615,10 +597,26 @@ public PagedIterable listStatuses() throws IOException { return owner.listCommitStatuses(sha); } - private GHUser resolveUser(User author) throws IOException { - if (author == null || author.login == null) - return null; - return owner.root().getUser(author.login); + /** + * Gets last status. + * + * @return the last status of this commit, which is what gets shown in the UI. + * @throws IOException + * on error + */ + public GHCommitStatus getLastStatus() throws IOException { + return owner.getLastCommitStatus(sha); + } + + /** + * Gets check-runs for given sha. + * + * @return check runs for given sha. + * @throws IOException + * on error + */ + public PagedIterable getCheckRuns() throws IOException { + return owner.getCheckRuns(sha); } /** diff --git a/src/main/java/org/kohsuke/github/GHCommitBuilder.java b/src/main/java/org/kohsuke/github/GHCommitBuilder.java index 65f4c6d679..11c382312b 100644 --- a/src/main/java/org/kohsuke/github/GHCommitBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitBuilder.java @@ -1,32 +1,37 @@ package org.kohsuke.github; import java.io.IOException; -import java.time.Instant; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.TimeZone; // TODO: Auto-generated Javadoc /** * Builder pattern for creating a new commit. Based on https://developer.github.com/v3/git/commits/#create-a-commit */ public class GHCommitBuilder { + private final GHRepository repo; + private final Requester req; + + private final List parents = new ArrayList(); + private static final class UserInfo { - private final String date; - private final String email; private final String name; + private final String email; + private final String date; - private UserInfo(String name, String email, Instant date) { + private UserInfo(String name, String email, Date date) { this.name = name; this.email = email; - this.date = GitHubClient.printInstant(date); + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + df.setTimeZone(tz); + this.date = df.format((date != null) ? date : new Date()); } } - private final List parents = new ArrayList(); - - private final GHRepository repo; - - private final Requester req; /** * Instantiates a new GH commit builder. @@ -40,57 +45,43 @@ private UserInfo(String name, String email, Instant date) { } /** - * Configures the author of this commit. + * Message gh commit builder. * - * @param name - * the name - * @param email - * the email - * @param date - * the date + * @param message + * the commit message * @return the gh commit builder - * @deprecated use {@link #author(String, String, Instant)} instead */ - @Deprecated - public GHCommitBuilder author(String name, String email, Date date) { - return author(name, email, GitHubClient.toInstantOrNull(date)); + public GHCommitBuilder message(String message) { + req.with("message", message); + return this; } /** - * Configures the author of this commit. + * Tree gh commit builder. * - * @param name - * the name - * @param email - * the email - * @param date - * the date + * @param tree + * the SHA of the tree object this commit points to * @return the gh commit builder */ - public GHCommitBuilder author(String name, String email, Instant date) { - req.with("author", new UserInfo(name, email, date)); + public GHCommitBuilder tree(String tree) { + req.with("tree", tree); return this; } /** - * Configures the committer of this commit. + * Parent gh commit builder. * - * @param name - * the name - * @param email - * the email - * @param date - * the date + * @param parent + * the SHA of a parent commit. * @return the gh commit builder - * @deprecated use {@link #committer(String, String, Instant)} instead */ - @Deprecated - public GHCommitBuilder committer(String name, String email, Date date) { - return committer(name, email, GitHubClient.toInstantOrNull(date)); + public GHCommitBuilder parent(String parent) { + parents.add(parent); + return this; } /** - * Configures the committer of this commit. + * Configures the author of this commit. * * @param name * the name @@ -100,73 +91,53 @@ public GHCommitBuilder committer(String name, String email, Date date) { * the date * @return the gh commit builder */ - public GHCommitBuilder committer(String name, String email, Instant date) { - req.with("committer", new UserInfo(name, email, date)); + public GHCommitBuilder author(String name, String email, Date date) { + req.with("author", new UserInfo(name, email, date)); return this; } /** - * Creates a blob based on the parameters specified thus far. + * Configures the PGP signature of this commit. * - * @return the gh commit - * @throws IOException - * the io exception - */ - public GHCommit create() throws IOException { - req.with("parents", parents); - return req.method("POST").withUrlPath(getApiTail()).fetch(GHCommit.class).wrapUp(repo); - } - - /** - * Message gh commit builder. + * @param signature + * the signature calculated from the commit * - * @param message - * the commit message * @return the gh commit builder */ - public GHCommitBuilder message(String message) { - req.with("message", message); + public GHCommitBuilder withSignature(String signature) { + req.with("signature", signature); return this; } /** - * Parent gh commit builder. + * Configures the committer of this commit. * - * @param parent - * the SHA of a parent commit. + * @param name + * the name + * @param email + * the email + * @param date + * the date * @return the gh commit builder */ - public GHCommitBuilder parent(String parent) { - parents.add(parent); + public GHCommitBuilder committer(String name, String email, Date date) { + req.with("committer", new UserInfo(name, email, date)); return this; } - /** - * Tree gh commit builder. - * - * @param tree - * the SHA of the tree object this commit points to - * @return the gh commit builder - */ - public GHCommitBuilder tree(String tree) { - req.with("tree", tree); - return this; + private String getApiTail() { + return String.format("/repos/%s/%s/git/commits", repo.getOwnerName(), repo.getName()); } /** - * Configures the PGP signature of this commit. - * - * @param signature - * the signature calculated from the commit + * Creates a blob based on the parameters specified thus far. * - * @return the gh commit builder + * @return the gh commit + * @throws IOException + * the io exception */ - public GHCommitBuilder withSignature(String signature) { - req.with("signature", signature); - return this; - } - - private String getApiTail() { - return String.format("/repos/%s/%s/git/commits", repo.getOwnerName(), repo.getName()); + public GHCommit create() throws IOException { + req.with("parents", parents); + return req.method("POST").withUrlPath(getApiTail()).fetch(GHCommit.class).wrapUp(repo); } } diff --git a/src/main/java/org/kohsuke/github/GHCommitComment.java b/src/main/java/org/kohsuke/github/GHCommitComment.java index b73a49666d..40427b41ea 100644 --- a/src/main/java/org/kohsuke/github/GHCommitComment.java +++ b/src/main/java/org/kohsuke/github/GHCommitComment.java @@ -19,10 +19,16 @@ justification = "JSON API") public class GHCommitComment extends GHObject implements Reactable { + /** + * Create default GHCommitComment instance + */ + public GHCommitComment() { + } + private GHRepository owner; /** The commit id. */ - String body, htmlUrl, commitId; + String body, html_url, commit_id; /** The line. */ Integer line; @@ -34,53 +40,33 @@ public class GHCommitComment extends GHObject implements Reactable { GHUser user; // not fully populated. beware. /** - * Create default GHCommitComment instance - */ - public GHCommitComment() { - } - - /** - * Creates the reaction. + * Gets owner. * - * @param content - * the content - * @return the GH reaction - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the owner */ - public GHReaction createReaction(ReactionContent content) throws IOException { - return owner.root() - .createRequest() - .method("POST") - .with("content", content.getContent()) - .withUrlPath(getApiTail() + "/reactions") - .fetch(GHReaction.class); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getOwner() { + return owner; } /** - * Deletes this comment. + * URL like + * 'https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000#commitcomment-1252827' to + * show this commit comment in a browser. * - * @throws IOException - * the io exception + * @return the html url */ - public void delete() throws IOException { - owner.root().createRequest().method("DELETE").withUrlPath(getApiTail()).send(); + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); } /** - * Delete reaction. + * Gets sha 1. * - * @param reaction - * the reaction - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the sha 1 */ - public void deleteReaction(GHReaction reaction) throws IOException { - owner.root() - .createRequest() - .method("DELETE") - .withUrlPath(getApiTail(), "reactions", String.valueOf(reaction.getId())) - .send(); + public String getSHA1() { + return commit_id; } /** @@ -93,25 +79,13 @@ public String getBody() { } /** - * Gets the commit to which this comment is associated with. - * - * @return the commit - * @throws IOException - * the io exception - */ - public GHCommit getCommit() throws IOException { - return getOwner().getCommit(getSHA1()); - } - - /** - * URL like - * 'https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000#commitcomment-1252827' to - * show this commit comment in a browser. + * A commit comment can be on a specific line of a specific file, if so, this field points to a file. Otherwise + * null. * - * @return the html url + * @return the path */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public String getPath() { + return path; } /** @@ -125,43 +99,77 @@ public int getLine() { } /** - * Gets owner. + * Gets the user who put this comment. * - * @return the owner + * @return the user + * @throws IOException + * the io exception */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return owner; + public GHUser getUser() throws IOException { + return owner == null || owner.isOffline() ? user : owner.root().getUser(user.login); } /** - * A commit comment can be on a specific line of a specific file, if so, this field points to a file. Otherwise - * null. + * Gets the commit to which this comment is associated with. * - * @return the path + * @return the commit + * @throws IOException + * the io exception */ - public String getPath() { - return path; + public GHCommit getCommit() throws IOException { + return getOwner().getCommit(getSHA1()); } /** - * Gets sha 1. + * Updates the body of the commit message. * - * @return the sha 1 + * @param body + * the body + * @throws IOException + * the io exception */ - public String getSHA1() { - return commitId; + public void update(String body) throws IOException { + owner.root() + .createRequest() + .method("PATCH") + .with("body", body) + .withUrlPath(getApiTail()) + .fetch(GHCommitComment.class); + this.body = body; } /** - * Gets the user who put this comment. + * Creates the reaction. * - * @return the user + * @param content + * the content + * @return the GH reaction * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public GHUser getUser() throws IOException { - return owner == null || owner.isOffline() ? user : owner.root().getUser(user.login); + public GHReaction createReaction(ReactionContent content) throws IOException { + return owner.root() + .createRequest() + .method("POST") + .with("content", content.getContent()) + .withUrlPath(getApiTail() + "/reactions") + .fetch(GHReaction.class); + } + + /** + * Delete reaction. + * + * @param reaction + * the reaction + * @throws IOException + * Signals that an I/O exception has occurred. + */ + public void deleteReaction(GHReaction reaction) throws IOException { + owner.root() + .createRequest() + .method("DELETE") + .withUrlPath(getApiTail(), "reactions", String.valueOf(reaction.getId())) + .send(); } /** @@ -177,21 +185,13 @@ public PagedIterable listReactions() { } /** - * Updates the body of the commit message. + * Deletes this comment. * - * @param body - * the body * @throws IOException * the io exception */ - public void update(String body) throws IOException { - owner.root() - .createRequest() - .method("PATCH") - .with("body", body) - .withUrlPath(getApiTail()) - .fetch(GHCommitComment.class); - this.body = body; + public void delete() throws IOException { + owner.root().createRequest().method("DELETE").withUrlPath(getApiTail()).send(); } private String getApiTail() { diff --git a/src/main/java/org/kohsuke/github/GHCommitFileIterable.java b/src/main/java/org/kohsuke/github/GHCommitFileIterable.java index 808f036017..8a3f02a6fe 100644 --- a/src/main/java/org/kohsuke/github/GHCommitFileIterable.java +++ b/src/main/java/org/kohsuke/github/GHCommitFileIterable.java @@ -21,9 +21,9 @@ class GHCommitFileIterable extends PagedIterable { */ private static final int GH_FILE_LIMIT_PER_COMMIT_PAGE = 300; - private final File[] files; private final GHRepository owner; private final String sha; + private final File[] files; /** * Instantiates a new GH commit iterable. diff --git a/src/main/java/org/kohsuke/github/GHCommitPointer.java b/src/main/java/org/kohsuke/github/GHCommitPointer.java index 41cb15114c..f56c214a50 100644 --- a/src/main/java/org/kohsuke/github/GHCommitPointer.java +++ b/src/main/java/org/kohsuke/github/GHCommitPointer.java @@ -35,34 +35,38 @@ */ public class GHCommitPointer { - private String ref, sha, label; - - private GHRepository repo; - private GHUser user; /** * Create default GHCommitPointer instance */ public GHCommitPointer() { } + private String ref, sha, label; + private GHUser user; + private GHRepository repo; + /** - * Obtains the commit that this pointer is referring to. + * This points to the user who owns the {@link #getRepository()}. * - * @return the commit + * @return the user * @throws IOException * the io exception */ - public GHCommit getCommit() throws IOException { - return getRepository().getCommit(getSha()); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getUser() throws IOException { + if (user != null) + return user.root().intern(user); + return user; } /** - * String that looks like "USERNAME:REF". + * The repository that contains the commit. * - * @return the label + * @return the repository */ - public String getLabel() { - return label; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getRepository() { + return repo; } /** @@ -75,34 +79,32 @@ public String getRef() { } /** - * The repository that contains the commit. + * SHA1 of the commit. * - * @return the repository + * @return the sha */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getRepository() { - return repo; + public String getSha() { + return sha; } /** - * SHA1 of the commit. + * String that looks like "USERNAME:REF". * - * @return the sha + * @return the label */ - public String getSha() { - return sha; + public String getLabel() { + return label; } /** - * This points to the user who owns the {@link #getRepository()}. + * Obtains the commit that this pointer is referring to. * - * @return the user + * @return the commit + * @throws IOException + * the io exception */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getUser() { - if (user != null) - return user.root().intern(user); - return user; + public GHCommit getCommit() throws IOException { + return getRepository().getCommit(getSha()); } } diff --git a/src/main/java/org/kohsuke/github/GHCommitQueryBuilder.java b/src/main/java/org/kohsuke/github/GHCommitQueryBuilder.java index 8a03adb62f..e9b8f0cca8 100644 --- a/src/main/java/org/kohsuke/github/GHCommitQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitQueryBuilder.java @@ -1,6 +1,5 @@ package org.kohsuke.github; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -21,8 +20,8 @@ * @see GHRepository#queryCommits() GHRepository#queryCommits() */ public class GHCommitQueryBuilder { - private final GHRepository repo; private final Requester req; + private final GHRepository repo; /** * Instantiates a new GH commit query builder. @@ -48,24 +47,27 @@ public GHCommitQueryBuilder author(String author) { } /** - * Specifies the SHA1 commit / tag / branch / etc to start listing commits from. + * Only commits containing this file path will be returned. * - * @param ref - * the ref + * @param path + * the path * @return the gh commit query builder */ - public GHCommitQueryBuilder from(String ref) { - req.with("sha", ref); + public GHCommitQueryBuilder path(String path) { + req.with("path", path); return this; } /** - * Lists up the commits with the criteria built so far. + * Specifies the SHA1 commit / tag / branch / etc to start listing commits from. * - * @return the paged iterable + * @param ref + * the ref + * @return the gh commit query builder */ - public PagedIterable list() { - return req.withUrlPath(repo.getApiTailUrl("commits")).toIterable(GHCommit[].class, item -> item.wrapUp(repo)); + public GHCommitQueryBuilder from(String ref) { + req.with("sha", ref); + return this; } /** @@ -80,40 +82,15 @@ public GHCommitQueryBuilder pageSize(int pageSize) { return this; } - /** - * Only commits containing this file path will be returned. - * - * @param path - * the path - * @return the gh commit query builder - */ - public GHCommitQueryBuilder path(String path) { - req.with("path", path); - return this; - } - /** * Only commits after this date will be returned. * * @param dt * the dt * @return the gh commit query builder - * @deprecated use {@link #since(Instant)} */ - @Deprecated public GHCommitQueryBuilder since(Date dt) { - return since(GitHubClient.toInstantOrNull(dt)); - } - - /** - * Only commits after this date will be returned. - * - * @param dt - * the dt - * @return the gh commit query builder - */ - public GHCommitQueryBuilder since(Instant dt) { - req.with("since", GitHubClient.printInstant(dt)); + req.with("since", GitHubClient.printDate(dt)); return this; } @@ -125,7 +102,7 @@ public GHCommitQueryBuilder since(Instant dt) { * @return the gh commit query builder */ public GHCommitQueryBuilder since(long timestamp) { - return since(Instant.ofEpochMilli(timestamp)); + return since(new Date(timestamp)); } /** @@ -134,33 +111,29 @@ public GHCommitQueryBuilder since(long timestamp) { * @param dt * the dt * @return the gh commit query builder - * @deprecated use {@link #until(Instant)} */ - @Deprecated public GHCommitQueryBuilder until(Date dt) { - return until(GitHubClient.toInstantOrNull(dt)); + req.with("until", GitHubClient.printDate(dt)); + return this; } /** * Only commits before this date will be returned. * - * @param dt - * the dt + * @param timestamp + * the timestamp * @return the gh commit query builder */ - public GHCommitQueryBuilder until(Instant dt) { - req.with("until", GitHubClient.printInstant(dt)); - return this; + public GHCommitQueryBuilder until(long timestamp) { + return until(new Date(timestamp)); } /** - * Only commits before this date will be returned. + * Lists up the commits with the criteria built so far. * - * @param timestamp - * the timestamp - * @return the gh commit query builder + * @return the paged iterable */ - public GHCommitQueryBuilder until(long timestamp) { - return until(Instant.ofEpochMilli(timestamp)); + public PagedIterable list() { + return req.withUrlPath(repo.getApiTailUrl("commits")).toIterable(GHCommit[].class, item -> item.wrapUp(repo)); } } diff --git a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java index 3a1ddbffce..28e34d66b8 100644 --- a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java @@ -15,80 +15,69 @@ public class GHCommitSearchBuilder extends GHSearchBuilder { /** - * The enum Sort. + * Instantiates a new GH commit search builder. + * + * @param root + * the root */ - public enum Sort { - - /** The author date. */ - AUTHOR_DATE, - /** The committer date. */ - COMMITTER_DATE + GHCommitSearchBuilder(GitHub root) { + super(root, CommitSearchResult.class); } - @SuppressFBWarnings( - value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, - justification = "JSON API") - private static class CommitSearchResult extends SearchResult { - private GHCommit[] items; - - @Override - GHCommit[] getItems(GitHub root) { - for (GHCommit commit : items) { - String repoName = getRepoName(commit.url); - try { - GHRepository repo = root.getRepository(repoName); - commit.wrapUp(repo); - } catch (IOException ioe) { - } - } - return items; - } + /** + * Search terms. + * + * @param term + * the term + * @return the GH commit search builder + */ + public GHCommitSearchBuilder q(String term) { + super.q(term); + return this; } /** - * @param commitUrl - * a commit URL - * @return the repo name ("username/reponame") + * Author gh commit search builder. + * + * @param v + * the v + * @return the gh commit search builder */ - private static String getRepoName(String commitUrl) { - if (StringUtils.isBlank(commitUrl)) { - return null; - } - int indexOfUsername = (GitHubClient.GITHUB_URL + "/repos/").length(); - String[] tokens = commitUrl.substring(indexOfUsername).split("/", 3); - return tokens[0] + '/' + tokens[1]; + public GHCommitSearchBuilder author(String v) { + return q("author:" + v); } /** - * Instantiates a new GH commit search builder. + * Committer gh commit search builder. * - * @param root - * the root + * @param v + * the v + * @return the gh commit search builder */ - GHCommitSearchBuilder(GitHub root) { - super(root, CommitSearchResult.class); + public GHCommitSearchBuilder committer(String v) { + return q("committer:" + v); } /** - * Author gh commit search builder. + * Author name gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder author(String v) { - return q("author:" + v); + public GHCommitSearchBuilder authorName(String v) { + return q("author-name:" + v); } /** - * Author date gh commit search builder. + * Committer name gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder authorDate(String v) { - return q("author-date:" + v); + public GHCommitSearchBuilder committerName(String v) { + return q("committer-name:" + v); } /** @@ -103,25 +92,25 @@ public GHCommitSearchBuilder authorEmail(String v) { } /** - * Author name gh commit search builder. + * Committer email gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder authorName(String v) { - return q("author-name:" + v); + public GHCommitSearchBuilder committerEmail(String v) { + return q("committer-email:" + v); } /** - * Committer gh commit search builder. + * Author date gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder committer(String v) { - return q("committer:" + v); + public GHCommitSearchBuilder authorDate(String v) { + return q("author-date:" + v); } /** @@ -136,70 +125,69 @@ public GHCommitSearchBuilder committerDate(String v) { } /** - * Committer email gh commit search builder. + * Merge gh commit search builder. * - * @param v - * the v + * @param merge + * the merge * @return the gh commit search builder */ - public GHCommitSearchBuilder committerEmail(String v) { - return q("committer-email:" + v); + public GHCommitSearchBuilder merge(boolean merge) { + return q("merge:" + Boolean.valueOf(merge).toString().toLowerCase()); } /** - * Committer name gh commit search builder. + * Hash gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder committerName(String v) { - return q("committer-name:" + v); + public GHCommitSearchBuilder hash(String v) { + return q("hash:" + v); } /** - * Hash gh commit search builder. + * Parent gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder hash(String v) { - return q("hash:" + v); + public GHCommitSearchBuilder parent(String v) { + return q("parent:" + v); } /** - * Is gh commit search builder. + * Tree gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder is(String v) { - return q("is:" + v); + public GHCommitSearchBuilder tree(String v) { + return q("tree:" + v); } /** - * Merge gh commit search builder. + * Is gh commit search builder. * - * @param merge - * the merge + * @param v + * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder merge(boolean merge) { - return q("merge:" + Boolean.valueOf(merge).toString().toLowerCase()); + public GHCommitSearchBuilder is(String v) { + return q("is:" + v); } /** - * Order gh commit search builder. + * User gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder order(GHDirection v) { - req.with("order", v); - return this; + public GHCommitSearchBuilder user(String v) { + return q("user:" + v); } /** @@ -214,37 +202,26 @@ public GHCommitSearchBuilder org(String v) { } /** - * Parent gh commit search builder. + * Repo gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder parent(String v) { - return q("parent:" + v); - } - - /** - * Search terms. - * - * @param term - * the term - * @return the GH commit search builder - */ - public GHCommitSearchBuilder q(String term) { - super.q(term); - return this; + public GHCommitSearchBuilder repo(String v) { + return q("repo:" + v); } /** - * Repo gh commit search builder. + * Order gh commit search builder. * * @param v * the v * @return the gh commit search builder */ - public GHCommitSearchBuilder repo(String v) { - return q("repo:" + v); + public GHCommitSearchBuilder order(GHDirection v) { + req.with("order", v); + return this; } /** @@ -260,25 +237,48 @@ public GHCommitSearchBuilder sort(Sort sort) { } /** - * Tree gh commit search builder. - * - * @param v - * the v - * @return the gh commit search builder + * The enum Sort. */ - public GHCommitSearchBuilder tree(String v) { - return q("tree:" + v); + public enum Sort { + + /** The author date. */ + AUTHOR_DATE, + /** The committer date. */ + COMMITTER_DATE + } + + @SuppressFBWarnings( + value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, + justification = "JSON API") + private static class CommitSearchResult extends SearchResult { + private GHCommit[] items; + + @Override + GHCommit[] getItems(GitHub root) { + for (GHCommit commit : items) { + String repoName = getRepoName(commit.url); + try { + GHRepository repo = root.getRepository(repoName); + commit.wrapUp(repo); + } catch (IOException ioe) { + } + } + return items; + } } /** - * User gh commit search builder. - * - * @param v - * the v - * @return the gh commit search builder + * @param commitUrl + * a commit URL + * @return the repo name ("username/reponame") */ - public GHCommitSearchBuilder user(String v) { - return q("user:" + v); + private static String getRepoName(String commitUrl) { + if (StringUtils.isBlank(commitUrl)) { + return null; + } + int indexOfUsername = (GitHubClient.GITHUB_URL + "/repos/").length(); + String[] tokens = commitUrl.substring(indexOfUsername).split("/", 3); + return tokens[0] + '/' + tokens[1]; } /** diff --git a/src/main/java/org/kohsuke/github/GHCommitState.java b/src/main/java/org/kohsuke/github/GHCommitState.java index 7a89a3dc72..bdefc01446 100644 --- a/src/main/java/org/kohsuke/github/GHCommitState.java +++ b/src/main/java/org/kohsuke/github/GHCommitState.java @@ -9,12 +9,12 @@ */ public enum GHCommitState { - /** The error. */ - ERROR, - /** The failure. */ - FAILURE, /** The pending. */ PENDING, /** The success. */ - SUCCESS + SUCCESS, + /** The error. */ + ERROR, + /** The failure. */ + FAILURE } diff --git a/src/main/java/org/kohsuke/github/GHCommitStatus.java b/src/main/java/org/kohsuke/github/GHCommitStatus.java index fe61d61ea7..524c4d119a 100644 --- a/src/main/java/org/kohsuke/github/GHCommitStatus.java +++ b/src/main/java/org/kohsuke/github/GHCommitStatus.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import java.io.IOException; + // TODO: Auto-generated Javadoc /** * Represents a status of a commit. @@ -12,40 +14,46 @@ */ public class GHCommitStatus extends GHObject { - /** The context. */ - String context; - - /** The creator. */ - GHUser creator; + /** + * Create default GHCommitStatus instance + */ + public GHCommitStatus() { + } /** The state. */ String state; /** The description. */ - String targetUrl, description; + String target_url, description; - /** - * Create default GHCommitStatus instance - */ - public GHCommitStatus() { - } + /** The context. */ + String context; + + /** The creator. */ + GHUser creator; /** - * Gets context. + * Gets state. * - * @return the context + * @return the state */ - public String getContext() { - return context; + public GHCommitState getState() { + for (GHCommitState s : GHCommitState.values()) { + if (s.name().equalsIgnoreCase(state)) + return s; + } + throw new IllegalStateException("Unexpected state: " + state); } /** - * Gets creator. + * The URL that this status is linked to. + *

+ * This is the URL specified when creating a commit status. * - * @return the creator + * @return the target url */ - public GHUser getCreator() { - return root().intern(creator); + public String getTargetUrl() { + return target_url; } /** @@ -58,27 +66,23 @@ public String getDescription() { } /** - * Gets state. + * Gets creator. * - * @return the state + * @return the creator + * @throws IOException + * the io exception */ - public GHCommitState getState() { - for (GHCommitState s : GHCommitState.values()) { - if (s.name().equalsIgnoreCase(state)) - return s; - } - throw new IllegalStateException("Unexpected state: " + state); + public GHUser getCreator() throws IOException { + return root().intern(creator); } /** - * The URL that this status is linked to. - *

- * This is the URL specified when creating a commit status. + * Gets context. * - * @return the target url + * @return the context */ - public String getTargetUrl() { - return targetUrl; + public String getContext() { + return context; } } diff --git a/src/main/java/org/kohsuke/github/GHCompare.java b/src/main/java/org/kohsuke/github/GHCompare.java index 48340fda36..cba09389a1 100644 --- a/src/main/java/org/kohsuke/github/GHCompare.java +++ b/src/main/java/org/kohsuke/github/GHCompare.java @@ -18,6 +18,208 @@ */ public class GHCompare { + /** + * Create default GHCompare instance + */ + public GHCompare() { + } + + private String url, html_url, permalink_url, diff_url, patch_url; + private Status status; + private int ahead_by, behind_by, total_commits; + private Commit base_commit, merge_base_commit; + private Commit[] commits; + private GHCommit.File[] files; + + private GHRepository owner; + + @JacksonInject("GHCompare_usePaginatedCommits") + private boolean usePaginatedCommits; + + /** + * Gets url. + * + * @return the url + */ + public URL getUrl() { + return GitHubClient.parseURL(url); + } + + /** + * Gets html url. + * + * @return the html url + */ + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); + } + + /** + * Gets permalink url. + * + * @return the permalink url + */ + public URL getPermalinkUrl() { + return GitHubClient.parseURL(permalink_url); + } + + /** + * Gets diff url. + * + * @return the diff url + */ + public URL getDiffUrl() { + return GitHubClient.parseURL(diff_url); + } + + /** + * Gets patch url. + * + * @return the patch url + */ + public URL getPatchUrl() { + return GitHubClient.parseURL(patch_url); + } + + /** + * Gets status. + * + * @return the status + */ + public Status getStatus() { + return status; + } + + /** + * Gets ahead by. + * + * @return the ahead by + */ + public int getAheadBy() { + return ahead_by; + } + + /** + * Gets behind by. + * + * @return the behind by + */ + public int getBehindBy() { + return behind_by; + } + + /** + * Gets total commits. + * + * @return the total commits + */ + public int getTotalCommits() { + return total_commits; + } + + /** + * Gets base commit. + * + * @return the base commit + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public Commit getBaseCommit() { + return base_commit; + } + + /** + * Gets merge base commit. + * + * @return the merge base commit + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public Commit getMergeBaseCommit() { + return merge_base_commit; + } + + /** + * Gets an array of commits. + * + * By default, the commit list is limited to 250 results. + * + * Since + * 2021-03-22, + * compare supports pagination of commits. This makes the initial {@link GHCompare} response return faster and + * supports comparisons with more than 250 commits. To read commits progressively using pagination, set + * {@link GHRepository#setCompareUsePaginatedCommits(boolean)} to true before calling + * {@link GHRepository#getCompare(String, String)}. + * + * @return A copy of the array being stored in the class. + */ + public Commit[] getCommits() { + try { + return listCommits().withPageSize(100).toArray(); + } catch (IOException e) { + throw new GHException(e.getMessage(), e); + } + } + + /** + * Iterable of commits for this comparison. + * + * By default, the commit list is limited to 250 results. + * + * Since + * 2021-03-22, + * compare supports pagination of commits. This makes the initial {@link GHCompare} response return faster and + * supports comparisons with more than 250 commits. To read commits progressively using pagination, set + * {@link GHRepository#setCompareUsePaginatedCommits(boolean)} to true before calling + * {@link GHRepository#getCompare(String, String)}. + * + * @return iterable of commits + */ + public PagedIterable listCommits() { + if (usePaginatedCommits) { + return new GHCompareCommitsIterable(); + } else { + // if not using paginated commits, adapt the returned commits array + return new PagedIterable() { + @Nonnull + @Override + public PagedIterator _iterator(int pageSize) { + return new PagedIterator<>(Collections.singleton(commits).iterator(), null); + } + }; + } + } + + /** + * Gets an array of files. + * + * By default, the file array is limited to 300 results. To retrieve the full list of files, iterate over each + * commit returned by {@link GHCompare#listCommits} and use {@link GHCommit#listFiles} to get the files for each + * commit. + * + * @return A copy of the array being stored in the class. + */ + public GHCommit.File[] getFiles() { + GHCommit.File[] newValue = new GHCommit.File[files.length]; + System.arraycopy(files, 0, newValue, 0, files.length); + return newValue; + } + + /** + * Wrap gh compare. + * + * @param owner + * the owner + * @return the gh compare + */ + GHCompare lateBind(GHRepository owner) { + this.owner = owner; + for (Commit commit : commits) { + commit.wrapUp(owner); + } + merge_base_commit.wrapUp(owner); + base_commit.wrapUp(owner); + return this; + } + /** * Compare commits had a child commit element with additional details we want to capture. This extension of GHCommit * provides that. @@ -26,14 +228,14 @@ public class GHCompare { justification = "JSON API") public static class Commit extends GHCommit { - private InnerCommit commit; - /** * Create default Commit instance */ public Commit() { } + private InnerCommit commit; + /** * Gets commit. * @@ -49,32 +251,32 @@ public InnerCommit getCommit() { */ public static class InnerCommit { - private GitUser author, committer; - - private Tree tree; - private String url, sha, message; /** * Create default InnerCommit instance */ public InnerCommit() { } + private String url, sha, message; + private GitUser author, committer; + private Tree tree; + /** - * Gets author. + * Gets url. * - * @return the author + * @return the url */ - public GitUser getAuthor() { - return author; + public String getUrl() { + return url; } /** - * Gets committer. + * Gets sha. * - * @return the committer + * @return the sha */ - public GitUser getCommitter() { - return committer; + public String getSha() { + return sha; } /** @@ -87,67 +289,45 @@ public String getMessage() { } /** - * Gets sha. + * Gets author. * - * @return the sha + * @return the author */ - public String getSha() { - return sha; + public GitUser getAuthor() { + return author; } /** - * Gets tree. + * Gets committer. * - * @return the tree + * @return the committer */ - public Tree getTree() { - return tree; + public GitUser getCommitter() { + return committer; } /** - * Gets url. + * Gets tree. * - * @return the url + * @return the tree */ - public String getUrl() { - return url; + public Tree getTree() { + return tree; } } - /** - * The enum Status. - */ - public static enum Status { - /** The ahead. */ - ahead, - /** The behind. */ - behind, - /** The diverged. */ - diverged, - /** The identical. */ - identical - } /** * The type Tree. */ public static class Tree { - private String url, sha; - /** * Create default Tree instance */ public Tree() { } - /** - * Gets sha. - * - * @return the sha - */ - public String getSha() { - return sha; - } + private String url, sha; /** * Gets url. @@ -157,7 +337,32 @@ public String getSha() { public String getUrl() { return url; } + + /** + * Gets sha. + * + * @return the sha + */ + public String getSha() { + return sha; + } + } + + /** + * The enum Status. + */ + public static enum Status { + + /** The behind. */ + behind, + /** The ahead. */ + ahead, + /** The identical. */ + identical, + /** The diverged. */ + diverged } + /** * Iterable for commit listing. */ @@ -219,209 +424,4 @@ public Commit[] next() { }; } } - private int aheadBy, behindBy, totalCommits; - private Commit baseCommit, mergeBaseCommit; - - private Commit[] commits; - - private GHCommit.File[] files; - - private GHRepository owner; - - private Status status; - - private String url, htmlUrl, permalinkUrl, diffUrl, patchUrl; - - @JacksonInject("GHCompare_usePaginatedCommits") - private boolean usePaginatedCommits; - - /** - * Create default GHCompare instance - */ - public GHCompare() { - } - - /** - * Gets ahead by. - * - * @return the ahead by - */ - public int getAheadBy() { - return aheadBy; - } - - /** - * Gets base commit. - * - * @return the base commit - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public Commit getBaseCommit() { - return baseCommit; - } - - /** - * Gets behind by. - * - * @return the behind by - */ - public int getBehindBy() { - return behindBy; - } - - /** - * Gets an array of commits. - * - * By default, the commit list is limited to 250 results. - * - * Since - * 2021-03-22, - * compare supports pagination of commits. This makes the initial {@link GHCompare} response return faster and - * supports comparisons with more than 250 commits. To read commits progressively using pagination, set - * {@link GHRepository#setCompareUsePaginatedCommits(boolean)} to true before calling - * {@link GHRepository#getCompare(String, String)}. - * - * @return A copy of the array being stored in the class. - */ - public Commit[] getCommits() { - try { - return listCommits().withPageSize(100).toArray(); - } catch (IOException e) { - throw new GHException(e.getMessage(), e); - } - } - - /** - * Gets diff url. - * - * @return the diff url - */ - public URL getDiffUrl() { - return GitHubClient.parseURL(diffUrl); - } - - /** - * Gets an array of files. - * - * By default, the file array is limited to 300 results. To retrieve the full list of files, iterate over each - * commit returned by {@link GHCompare#listCommits} and use {@link GHCommit#listFiles} to get the files for each - * commit. - * - * @return A copy of the array being stored in the class. - */ - public GHCommit.File[] getFiles() { - GHCommit.File[] newValue = new GHCommit.File[files.length]; - System.arraycopy(files, 0, newValue, 0, files.length); - return newValue; - } - - /** - * Gets html url. - * - * @return the html url - */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); - } - - /** - * Gets merge base commit. - * - * @return the merge base commit - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public Commit getMergeBaseCommit() { - return mergeBaseCommit; - } - - /** - * Gets patch url. - * - * @return the patch url - */ - public URL getPatchUrl() { - return GitHubClient.parseURL(patchUrl); - } - - /** - * Gets permalink url. - * - * @return the permalink url - */ - public URL getPermalinkUrl() { - return GitHubClient.parseURL(permalinkUrl); - } - - /** - * Gets status. - * - * @return the status - */ - public Status getStatus() { - return status; - } - - /** - * Gets total commits. - * - * @return the total commits - */ - public int getTotalCommits() { - return totalCommits; - } - - /** - * Gets url. - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(url); - } - - /** - * Iterable of commits for this comparison. - * - * By default, the commit list is limited to 250 results. - * - * Since - * 2021-03-22, - * compare supports pagination of commits. This makes the initial {@link GHCompare} response return faster and - * supports comparisons with more than 250 commits. To read commits progressively using pagination, set - * {@link GHRepository#setCompareUsePaginatedCommits(boolean)} to true before calling - * {@link GHRepository#getCompare(String, String)}. - * - * @return iterable of commits - */ - public PagedIterable listCommits() { - if (usePaginatedCommits) { - return new GHCompareCommitsIterable(); - } else { - // if not using paginated commits, adapt the returned commits array - return new PagedIterable() { - @Nonnull - @Override - public PagedIterator _iterator(int pageSize) { - return new PagedIterator<>(Collections.singleton(commits).iterator(), null); - } - }; - } - } - - /** - * Wrap gh compare. - * - * @param owner - * the owner - * @return the gh compare - */ - GHCompare lateBind(GHRepository owner) { - this.owner = owner; - for (Commit commit : commits) { - commit.wrapUp(owner); - } - mergeBaseCommit.wrapUp(owner); - baseCommit.wrapUp(owner); - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHContent.java b/src/main/java/org/kohsuke/github/GHContent.java index d6d9549b01..2bfc2a1bcc 100644 --- a/src/main/java/org/kohsuke/github/GHContent.java +++ b/src/main/java/org/kohsuke/github/GHContent.java @@ -19,83 +19,101 @@ public class GHContent extends GitHubInteractiveObject implements Refreshable { /** - * Gets the api route. - * - * @param repository - * the repository - * @param path - * the path - * @return the api route + * Create default GHContent instance */ - static String getApiRoute(GHRepository repository, String path) { - return repository.getApiTailUrl("contents/" + path); + public GHContent() { } - private String content; - - private String downloadUrl; - private String encoding; - private String gitUrl; // this is the Blob url - private String htmlUrl; // this is the UI - private String name; - private String path; /* * In normal use of this class, repository field is set via wrap(), but in the code search API, there's a nested * 'repository' field that gets populated from JSON. */ private GHRepository repository; - private String sha; + + private String type; + private String encoding; private long size; + private String sha; + private String name; + private String path; private String target; - private String type; + private String content; private String url; // this is the API url + private String git_url; // this is the Blob url + private String html_url; // this is the UI + private String download_url; /** - * Create default GHContent instance + * Gets owner. + * + * @return the owner */ - public GHContent() { + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getOwner() { + return repository; } /** - * Delete gh content update response. + * Gets type. * - * @param message - * the message - * @return the gh content update response - * @throws IOException - * the io exception + * @return the type */ - public GHContentUpdateResponse delete(String message) throws IOException { - return delete(message, null); + public String getType() { + return type; } /** - * Delete gh content update response. + * Gets encoding. * - * @param commitMessage - * the commit message - * @param branch - * the branch - * @return the gh content update response - * @throws IOException - * the io exception + * @return the encoding */ - public GHContentUpdateResponse delete(String commitMessage, String branch) throws IOException { - Requester requester = root().createRequest() - .method("DELETE") - .with("path", path) - .with("message", commitMessage) - .with("sha", sha); + public String getEncoding() { + return encoding; + } - if (branch != null) { - requester.with("branch", branch); - } + /** + * Gets size. + * + * @return the size + */ + public long getSize() { + return size; + } - GHContentUpdateResponse response = requester.withUrlPath(getApiRoute(repository, path)) - .fetch(GHContentUpdateResponse.class); + /** + * Gets sha. + * + * @return the sha + */ + public String getSha() { + return sha; + } - response.getCommit().wrapUp(repository); - return response; + /** + * Gets name. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Gets path. + * + * @return the path + */ + public String getPath() { + return path; + } + + /** + * Gets target of a symlink. This will only be set if {@code "symlink".equals(getType())} + * + * @return the target + */ + public String getTarget() { + return target; } /** @@ -116,18 +134,6 @@ public String getContent() throws IOException { return new String(readDecodedContent()); } - /** - * URL to retrieve the raw content of the file. Null if this is a directory. - * - * @return the download url - * @throws IOException - * the io exception - */ - public String getDownloadUrl() throws IOException { - refresh(downloadUrl); - return downloadUrl; - } - /** * Retrieve the base64-encoded content that is stored at this location. * @@ -147,12 +153,12 @@ public String getEncodedContent() throws IOException { } /** - * Gets encoding. + * Gets url. * - * @return the encoding + * @return the url */ - public String getEncoding() { - return encoding; + public String getUrl() { + return url; } /** @@ -161,7 +167,7 @@ public String getEncoding() { * @return the git url */ public String getGitUrl() { - return gitUrl; + return git_url; } /** @@ -170,80 +176,60 @@ public String getGitUrl() { * @return the html url */ public String getHtmlUrl() { - return htmlUrl; - } - - /** - * Gets name. - * - * @return the name - */ - public String getName() { - return name; - } - - /** - * Gets owner. - * - * @return the owner - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return repository; - } - - /** - * Gets path. - * - * @return the path - */ - public String getPath() { - return path; + return html_url; } /** - * Gets sha. + * Retrieves the actual bytes of the blob. * - * @return the sha + * @return the input stream + * @throws IOException + * the io exception */ - public String getSha() { - return sha; + public InputStream read() throws IOException { + return new ByteArrayInputStream(readDecodedContent()); } /** - * Gets size. + * Retrieves the decoded bytes of the blob. * - * @return the size + * @return the input stream + * @throws IOException + * the io exception */ - public long getSize() { - return size; - } + private byte[] readDecodedContent() throws IOException { + String encodedContent = getEncodedContent(); + if (encoding.equals("base64")) { + try { + Base64.Decoder decoder = Base64.getMimeDecoder(); + return decoder.decode(encodedContent.getBytes(StandardCharsets.US_ASCII)); + } catch (IllegalArgumentException e) { + throw new AssertionError(e); // US-ASCII is mandatory + } + } - /** - * Gets target of a symlink. This will only be set if {@code "symlink".equals(getType())} - * - * @return the target - */ - public String getTarget() { - return target; + throw new UnsupportedOperationException("Unrecognized encoding: " + encoding); } /** - * Gets type. + * URL to retrieve the raw content of the file. Null if this is a directory. * - * @return the type + * @return the download url + * @throws IOException + * the io exception */ - public String getType() { - return type; + public String getDownloadUrl() throws IOException { + refresh(download_url); + return download_url; } /** - * Gets url. + * Is file boolean. * - * @return the url + * @return the boolean */ - public String getUrl() { - return url; + public boolean isFile() { + return "file".equals(type); } /** @@ -256,50 +242,31 @@ public boolean isDirectory() { } /** - * Is file boolean. + * Fully populate the data by retrieving missing data. + *

+ * Depending on the original API call where this object is created, it may not contain everything. * - * @return the boolean + * @throws IOException + * the io exception */ - public boolean isFile() { - return "file".equals(type); + protected synchronized void populate() throws IOException { + root().createRequest().withUrlPath(url).fetchInto(this); } /** * List immediate children of this directory. * * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listDirectoryContent() { + public PagedIterable listDirectoryContent() throws IOException { if (!isDirectory()) throw new IllegalStateException(path + " is not a directory"); return root().createRequest().setRawUrlPath(url).toIterable(GHContent[].class, item -> item.wrap(repository)); } - /** - * Retrieves the actual bytes of the blob. - * - * @return the input stream - * @throws IOException - * the io exception - */ - public InputStream read() throws IOException { - return new ByteArrayInputStream(readDecodedContent()); - } - - /** - * Fully populate the data by retrieving missing data. - * - * Depending on the original API call where this object is created, it may not contain everything. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Override - public synchronized void refresh() throws IOException { - root().createRequest().setRawUrlPath(url).fetchInto(this); - } - /** * Update gh content update response. * @@ -388,36 +355,58 @@ public GHContentUpdateResponse update(byte[] newContentBytes, String commitMessa } /** - * Retrieves the decoded bytes of the blob. + * Delete gh content update response. * - * @return the input stream + * @param message + * the message + * @return the gh content update response * @throws IOException * the io exception */ - private byte[] readDecodedContent() throws IOException { - String encodedContent = getEncodedContent(); - if (encoding.equals("base64")) { - try { - Base64.Decoder decoder = Base64.getMimeDecoder(); - return decoder.decode(encodedContent.getBytes(StandardCharsets.US_ASCII)); - } catch (IllegalArgumentException e) { - throw new AssertionError(e); // US-ASCII is mandatory - } - } - - throw new UnsupportedOperationException("Unrecognized encoding: " + encoding); + public GHContentUpdateResponse delete(String message) throws IOException { + return delete(message, null); } /** - * Fully populate the data by retrieving missing data. - *

- * Depending on the original API call where this object is created, it may not contain everything. + * Delete gh content update response. * + * @param commitMessage + * the commit message + * @param branch + * the branch + * @return the gh content update response * @throws IOException * the io exception */ - protected synchronized void populate() throws IOException { - root().createRequest().withUrlPath(url).fetchInto(this); + public GHContentUpdateResponse delete(String commitMessage, String branch) throws IOException { + Requester requester = root().createRequest() + .method("DELETE") + .with("path", path) + .with("message", commitMessage) + .with("sha", sha); + + if (branch != null) { + requester.with("branch", branch); + } + + GHContentUpdateResponse response = requester.withUrlPath(getApiRoute(repository, path)) + .fetch(GHContentUpdateResponse.class); + + response.getCommit().wrapUp(repository); + return response; + } + + /** + * Gets the api route. + * + * @param repository + * the repository + * @param path + * the path + * @return the api route + */ + static String getApiRoute(GHRepository repository, String path) { + return repository.getApiTailUrl("contents/" + path); } /** @@ -431,4 +420,17 @@ GHContent wrap(GHRepository owner) { this.repository = owner; return this; } + + /** + * Fully populate the data by retrieving missing data. + * + * Depending on the original API call where this object is created, it may not contain everything. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Override + public synchronized void refresh() throws IOException { + root().createRequest().setRawUrlPath(url).fetchInto(this); + } } diff --git a/src/main/java/org/kohsuke/github/GHContentBuilder.java b/src/main/java/org/kohsuke/github/GHContentBuilder.java index 11a77ab1b8..9b24af92b0 100644 --- a/src/main/java/org/kohsuke/github/GHContentBuilder.java +++ b/src/main/java/org/kohsuke/github/GHContentBuilder.java @@ -15,9 +15,9 @@ * @see GHRepository#createContent() GHRepository#createContent() */ public final class GHContentBuilder { - private String path; private final GHRepository repo; private final Requester req; + private String path; /** * Instantiates a new GH content builder. @@ -30,6 +30,19 @@ public final class GHContentBuilder { this.req = repo.root().createRequest().method("PUT"); } + /** + * Path gh content builder. + * + * @param path + * the path + * @return the gh content builder + */ + public GHContentBuilder path(String path) { + this.path = path; + req.with("path", path); + return this; + } + /** * Branch gh content builder. * @@ -43,20 +56,15 @@ public GHContentBuilder branch(String branch) { } /** - * Commits a new content. + * Used when updating (but not creating a new content) to specify the blob SHA of the file being replaced. * - * @return the gh content update response - * @throws IOException - * the io exception + * @param sha + * the sha + * @return the gh content builder */ - public GHContentUpdateResponse commit() throws IOException { - GHContentUpdateResponse response = req.withUrlPath(GHContent.getApiRoute(repo, path)) - .fetch(GHContentUpdateResponse.class); - - response.getContent().wrap(repo); - response.getCommit().wrapUp(repo); - - return response; + public GHContentBuilder sha(String sha) { + req.with("sha", sha); + return this; } /** @@ -66,8 +74,9 @@ public GHContentUpdateResponse commit() throws IOException { * the content * @return the gh content builder */ - public GHContentBuilder content(String content) { - return content(content.getBytes(StandardCharsets.UTF_8)); + public GHContentBuilder content(byte[] content) { + req.with("content", Base64.getEncoder().encodeToString(content)); + return this; } /** @@ -77,9 +86,8 @@ public GHContentBuilder content(String content) { * the content * @return the gh content builder */ - public GHContentBuilder content(byte[] content) { - req.with("content", Base64.getEncoder().encodeToString(content)); - return this; + public GHContentBuilder content(String content) { + return content(content.getBytes(StandardCharsets.UTF_8)); } /** @@ -95,27 +103,19 @@ public GHContentBuilder message(String commitMessage) { } /** - * Path gh content builder. + * Commits a new content. * - * @param path - * the path - * @return the gh content builder + * @return the gh content update response + * @throws IOException + * the io exception */ - public GHContentBuilder path(String path) { - this.path = path; - req.with("path", path); - return this; - } + public GHContentUpdateResponse commit() throws IOException { + GHContentUpdateResponse response = req.withUrlPath(GHContent.getApiRoute(repo, path)) + .fetch(GHContentUpdateResponse.class); - /** - * Used when updating (but not creating a new content) to specify the blob SHA of the file being replaced. - * - * @param sha - * the sha - * @return the gh content builder - */ - public GHContentBuilder sha(String sha) { - req.with("sha", sha); - return this; + response.getContent().wrap(repo); + response.getCommit().wrapUp(repo); + + return response; } } diff --git a/src/main/java/org/kohsuke/github/GHContentSearchBuilder.java b/src/main/java/org/kohsuke/github/GHContentSearchBuilder.java index bdd16cea3e..e29449e6bb 100644 --- a/src/main/java/org/kohsuke/github/GHContentSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHContentSearchBuilder.java @@ -9,26 +9,6 @@ */ public class GHContentSearchBuilder extends GHSearchBuilder { - /** - * The enum Sort. - */ - public enum Sort { - - /** The best match. */ - BEST_MATCH, - /** The indexed. */ - INDEXED - } - - private static class ContentSearchResult extends SearchResult { - private GHContent[] items; - - @Override - GHContent[] getItems(GitHub root) { - return items; - } - } - /** * Instantiates a new GH content search builder. * @@ -40,25 +20,43 @@ GHContent[] getItems(GitHub root) { } /** - * Extension gh content search builder. + * {@inheritDoc} + */ + @Override + public GHContentSearchBuilder q(String term) { + super.q(term); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + GHContentSearchBuilder q(String qualifier, String value) { + super.q(qualifier, value); + return this; + } + + /** + * In gh content search builder. * * @param v * the v * @return the gh content search builder */ - public GHContentSearchBuilder extension(String v) { - return q("extension:" + v); + public GHContentSearchBuilder in(String v) { + return q("in:" + v); } /** - * Filename gh content search builder. + * Language gh content search builder. * * @param v * the v * @return the gh content search builder */ - public GHContentSearchBuilder filename(String v) { - return q("filename:" + v); + public GHContentSearchBuilder language(String v) { + return q("language:" + v); } /** @@ -78,57 +76,58 @@ public GHContentSearchBuilder fork(GHFork fork) { } /** - * In gh content search builder. + * Size gh content search builder. * * @param v * the v * @return the gh content search builder */ - public GHContentSearchBuilder in(String v) { - return q("in:" + v); + public GHContentSearchBuilder size(String v) { + return q("size:" + v); } /** - * Language gh content search builder. + * Path gh content search builder. * * @param v * the v * @return the gh content search builder */ - public GHContentSearchBuilder language(String v) { - return q("language:" + v); + public GHContentSearchBuilder path(String v) { + return q("path:" + v); } /** - * Order gh content search builder. + * Filename gh content search builder. * * @param v * the v * @return the gh content search builder */ - public GHContentSearchBuilder order(GHDirection v) { - req.with("order", v); - return this; + public GHContentSearchBuilder filename(String v) { + return q("filename:" + v); } /** - * Path gh content search builder. + * Extension gh content search builder. * * @param v * the v * @return the gh content search builder */ - public GHContentSearchBuilder path(String v) { - return q("path:" + v); + public GHContentSearchBuilder extension(String v) { + return q("extension:" + v); } /** - * {@inheritDoc} + * User gh content search builder. + * + * @param v + * the v + * @return the gh content search builder */ - @Override - public GHContentSearchBuilder q(String term) { - super.q(term); - return this; + public GHContentSearchBuilder user(String v) { + return q("user:" + v); } /** @@ -143,14 +142,15 @@ public GHContentSearchBuilder repo(String v) { } /** - * Size gh content search builder. + * Order gh content search builder. * * @param v * the v * @return the gh content search builder */ - public GHContentSearchBuilder size(String v) { - return q("size:" + v); + public GHContentSearchBuilder order(GHDirection v) { + req.with("order", v); + return this; } /** @@ -170,14 +170,23 @@ public GHContentSearchBuilder sort(GHContentSearchBuilder.Sort sort) { } /** - * User gh content search builder. - * - * @param v - * the v - * @return the gh content search builder + * The enum Sort. */ - public GHContentSearchBuilder user(String v) { - return q("user:" + v); + public enum Sort { + + /** The best match. */ + BEST_MATCH, + /** The indexed. */ + INDEXED + } + + private static class ContentSearchResult extends SearchResult { + private GHContent[] items; + + @Override + GHContent[] getItems(GitHub root) { + return items; + } } /** @@ -189,13 +198,4 @@ public GHContentSearchBuilder user(String v) { protected String getApiUrl() { return "/search/code"; } - - /** - * {@inheritDoc} - */ - @Override - GHContentSearchBuilder q(String qualifier, String value) { - super.q(qualifier, value); - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHContentUpdateResponse.java b/src/main/java/org/kohsuke/github/GHContentUpdateResponse.java index 193ed2bd1f..3703023140 100644 --- a/src/main/java/org/kohsuke/github/GHContentUpdateResponse.java +++ b/src/main/java/org/kohsuke/github/GHContentUpdateResponse.java @@ -8,33 +8,33 @@ */ public class GHContentUpdateResponse { - private GitCommit commit; - - private GHContent content; /** * Create default GHContentUpdateResponse instance */ public GHContentUpdateResponse() { } + private GHContent content; + private GitCommit commit; + /** - * Gets commit. + * Gets content. * - * @return the commit + * @return the content */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GitCommit getCommit() { - return commit; + public GHContent getContent() { + return content; } /** - * Gets content. + * Gets commit. * - * @return the content + * @return the commit */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHContent getContent() { - return content; + public GitCommit getCommit() { + return commit; } } diff --git a/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java b/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java index 9a787a1cb9..15bceb2ebd 100644 --- a/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java @@ -32,6 +32,32 @@ public GHCreateRepositoryBuilder(String name, GitHub root, String apiTail) { } } + /** + * Creates a default .gitignore + * + * @param language + * template to base the ignore file on + * @return a builder to continue with building See https://developer.github.com/v3/repos/#create + * @throws IOException + * In case of any networking error or error from the server. + */ + public GHCreateRepositoryBuilder gitignoreTemplate(String language) throws IOException { + return with("gitignore_template", language); + } + + /** + * Desired license template to apply. + * + * @param license + * template to base the license file on + * @return a builder to continue with building See https://developer.github.com/v3/repos/#create + * @throws IOException + * In case of any networking error or error from the server. + */ + public GHCreateRepositoryBuilder licenseTemplate(String license) throws IOException { + return with("license_template", license); + } + /** * If true, create an initial commit with empty README. * @@ -46,29 +72,31 @@ public GHCreateRepositoryBuilder autoInit(boolean enabled) throws IOException { } /** - * Creates a repository with all the parameters. + * The team that gets granted access to this repository. Only valid for creating a repository in an organization. * - * @return the gh repository + * @param team + * team to grant access to + * @return a builder to continue with building * @throws IOException - * if repository cannot be created + * In case of any networking error or error from the server. */ - public GHRepository create() throws IOException { - return done(); + public GHCreateRepositoryBuilder team(GHTeam team) throws IOException { + if (team != null) + return with("team_id", team.getId()); + return this; } /** - * Create repository from template repository. + * Specifies the ownership of the repository. * - * @param templateRepository - * the template repository as a GHRepository + * @param owner + * organization or personage * @return a builder to continue with building + * @throws IOException + * In case of any networking error or error from the server. */ - public GHCreateRepositoryBuilder fromTemplateRepository(GHRepository templateRepository) { - Objects.requireNonNull(templateRepository, "templateRepository cannot be null"); - if (!templateRepository.isTemplate()) { - throw new IllegalArgumentException("The provided repository is not a template repository."); - } - return fromTemplateRepository(templateRepository.getOwnerName(), templateRepository.getName()); + public GHCreateRepositoryBuilder owner(String owner) throws IOException { + return with("owner", owner); } /** @@ -86,56 +114,28 @@ public GHCreateRepositoryBuilder fromTemplateRepository(String templateOwner, St } /** - * Creates a default .gitignore - * - * @param language - * template to base the ignore file on - * @return a builder to continue with building See https://developer.github.com/v3/repos/#create - * @throws IOException - * In case of any networking error or error from the server. - */ - public GHCreateRepositoryBuilder gitignoreTemplate(String language) throws IOException { - return with("gitignore_template", language); - } - - /** - * Desired license template to apply. - * - * @param license - * template to base the license file on - * @return a builder to continue with building See https://developer.github.com/v3/repos/#create - * @throws IOException - * In case of any networking error or error from the server. - */ - public GHCreateRepositoryBuilder licenseTemplate(String license) throws IOException { - return with("license_template", license); - } - - /** - * Specifies the ownership of the repository. + * Create repository from template repository. * - * @param owner - * organization or personage + * @param templateRepository + * the template repository as a GHRepository * @return a builder to continue with building - * @throws IOException - * In case of any networking error or error from the server. */ - public GHCreateRepositoryBuilder owner(String owner) throws IOException { - return with("owner", owner); + public GHCreateRepositoryBuilder fromTemplateRepository(GHRepository templateRepository) { + Objects.requireNonNull(templateRepository, "templateRepository cannot be null"); + if (!templateRepository.isTemplate()) { + throw new IllegalArgumentException("The provided repository is not a template repository."); + } + return fromTemplateRepository(templateRepository.getOwnerName(), templateRepository.getName()); } /** - * The team that gets granted access to this repository. Only valid for creating a repository in an organization. + * Creates a repository with all the parameters. * - * @param team - * team to grant access to - * @return a builder to continue with building + * @return the gh repository * @throws IOException - * In case of any networking error or error from the server. + * if repository cannot be created */ - public GHCreateRepositoryBuilder team(GHTeam team) throws IOException { - if (team != null) - return with("team_id", team.getId()); - return this; + public GHRepository create() throws IOException { + return done(); } } diff --git a/src/main/java/org/kohsuke/github/GHDeployKey.java b/src/main/java/org/kohsuke/github/GHDeployKey.java index cba3e243c7..50a7743688 100644 --- a/src/main/java/org/kohsuke/github/GHDeployKey.java +++ b/src/main/java/org/kohsuke/github/GHDeployKey.java @@ -1,10 +1,8 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import org.apache.commons.lang3.builder.ToStringBuilder; import java.io.IOException; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -13,21 +11,11 @@ */ public class GHDeployKey { - /** Name of user that added the deploy key */ - private String addedBy; - - /** Creation date of the deploy key */ - private String createdAt; - - /** Last used date of the deploy key */ - private String lastUsed; - - private GHRepository owner; - /** Whether the deploykey has readonly permission or full access */ - private boolean readOnly; - - /** The id. */ - protected long id; + /** + * Create default GHDeployKey instance + */ + public GHDeployKey() { + } /** The title. */ protected String url, key, title; @@ -35,55 +23,21 @@ public class GHDeployKey { /** The verified. */ protected boolean verified; - /** - * Create default GHDeployKey instance - */ - public GHDeployKey() { - } + /** The id. */ + protected long id; + private GHRepository owner; - /** - * Delete. - * - * @throws IOException - * the io exception - */ - public void delete() throws IOException { - owner.root() - .createRequest() - .method("DELETE") - .withUrlPath(String.format("/repos/%s/%s/keys/%d", owner.getOwnerName(), owner.getName(), id)) - .send(); - } + /** Creation date of the deploy key */ + private String created_at; - /** - * Gets added_by - * - * @return the added_by - */ - public String getAddedBy() { - return addedBy; - } + /** Last used date of the deploy key */ + private String last_used; - /** - * Gets added_by - * - * @return the added_by - * @deprecated Use {@link #getAddedBy()} - */ - @Deprecated - public String getAdded_by() { - return getAddedBy(); - } + /** Name of user that added the deploy key */ + private String added_by; - /** - * Gets createdAt. - * - * @return the createdAt - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCreatedAt() { - return GitHubClient.parseInstant(createdAt); - } + /** Whether the deploykey has readonly permission or full access */ + private boolean read_only; /** * Gets id. @@ -103,16 +57,6 @@ public String getKey() { return key; } - /** - * Gets last_used. - * - * @return the last_used - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getLastUsedAt() { - return GitHubClient.parseInstant(lastUsed); - } - /** * Gets title. * @@ -132,32 +76,60 @@ public String getUrl() { } /** - * Is read_only + * Is verified boolean. * - * @return true if the key can only read. False if the key has write permission as well. + * @return the boolean + */ + public boolean isVerified() { + return verified; + } + + /** + * Gets created_at. + * + * @return the created_at */ - public boolean isReadOnly() { - return readOnly; + public Date getCreatedAt() { + return GitHubClient.parseDate(created_at); + } + + /** + * Gets last_used. + * + * @return the last_used + */ + public Date getLastUsedAt() { + return GitHubClient.parseDate(last_used); + } + + /** + * Gets added_by + * + * @return the added_by + */ + public String getAdded_by() { + return added_by; } /** * Is read_only * * @return true if the key can only read. False if the key has write permission as well. - * @deprecated {@link #isReadOnly()} */ - @Deprecated public boolean isRead_only() { - return isReadOnly(); + return read_only; } /** - * Is verified boolean. + * Wrap gh deploy key. * - * @return the boolean + * @param repo + * the repo + * @return the gh deploy key */ - public boolean isVerified() { - return verified; + GHDeployKey lateBind(GHRepository repo) { + this.owner = repo; + return this; } /** @@ -169,22 +141,24 @@ public String toString() { return new ToStringBuilder(this).append("title", title) .append("id", id) .append("key", key) - .append("created_at", createdAt) - .append("last_used", lastUsed) - .append("added_by", addedBy) - .append("read_only", readOnly) + .append("created_at", created_at) + .append("last_used", last_used) + .append("added_by", added_by) + .append("read_only", read_only) .toString(); } /** - * Wrap gh deploy key. + * Delete. * - * @param repo - * the repo - * @return the gh deploy key + * @throws IOException + * the io exception */ - GHDeployKey lateBind(GHRepository repo) { - this.owner = repo; - return this; + public void delete() throws IOException { + owner.root() + .createRequest() + .method("DELETE") + .withUrlPath(String.format("/repos/%s/%s/keys/%d", owner.getOwnerName(), owner.getName(), id)) + .send(); } } diff --git a/src/main/java/org/kohsuke/github/GHDeployment.java b/src/main/java/org/kohsuke/github/GHDeployment.java index 95770de8c4..ae18580667 100644 --- a/src/main/java/org/kohsuke/github/GHDeployment.java +++ b/src/main/java/org/kohsuke/github/GHDeployment.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import java.io.IOException; import java.net.URL; import java.util.Collections; import java.util.Map; @@ -15,86 +16,87 @@ */ public class GHDeployment extends GHObject { - private GHRepository owner; + /** + * Create default GHDeployment instance + */ + public GHDeployment() { + } - /** The creator. */ - protected GHUser creator; + private GHRepository owner; - /** The description. */ - protected String description; + /** The sha. */ + protected String sha; - /** The environment. */ - protected String environment; + /** The ref. */ + protected String ref; - /** The original environment. */ - protected String originalEnvironment; + /** The task. */ + protected String task; /** The payload. */ protected Object payload; - /** The production environment. */ - protected boolean productionEnvironment; + /** The environment. */ + protected String environment; - /** The ref. */ - protected String ref; + /** The description. */ + protected String description; - /** The repository url. */ - protected String repositoryUrl; + /** The statuses url. */ + protected String statuses_url; - /** The sha. */ - protected String sha; + /** The repository url. */ + protected String repository_url; - /** The statuses url. */ - protected String statusesUrl; + /** The creator. */ + protected GHUser creator; - /** The task. */ - protected String task; + /** The original environment. */ + protected String original_environment; /** The transient environment. */ - protected boolean transientEnvironment; + protected boolean transient_environment; - /** - * Create default GHDeployment instance - */ - public GHDeployment() { - } + /** The production environment. */ + protected boolean production_environment; /** - * Create status gh deployment status builder. + * Wrap. * - * @param state - * the state - * @return the gh deployment status builder + * @param owner + * the owner + * @return the GH deployment */ - public GHDeploymentStatusBuilder createStatus(GHDeploymentState state) { - return new GHDeploymentStatusBuilder(owner, getId(), state); + GHDeployment wrap(GHRepository owner) { + this.owner = owner; + return this; } /** - * Gets creator. + * Gets statuses url. * - * @return the creator + * @return the statuses url */ - public GHUser getCreator() { - return root().intern(creator); + public URL getStatusesUrl() { + return GitHubClient.parseURL(statuses_url); } /** - * Gets environment. + * Gets repository url. * - * @return the environment + * @return the repository url */ - public String getEnvironment() { - return environment; + public URL getRepositoryUrl() { + return GitHubClient.parseURL(repository_url); } /** - * The environment defined when the deployment was first created. + * Gets task. * - * @return the original deployment environment + * @return the task */ - public String getOriginalEnvironment() { - return originalEnvironment; + public String getTask() { + return task; } /** @@ -127,67 +129,80 @@ public Object getPayloadObject() { } /** - * Gets ref. + * The environment defined when the deployment was first created. * - * @return the ref + * @return the original deployment environment */ - public String getRef() { - return ref; + public String getOriginalEnvironment() { + return original_environment; } /** - * Gets repository url. + * Gets environment. * - * @return the repository url + * @return the environment */ - public URL getRepositoryUrl() { - return GitHubClient.parseURL(repositoryUrl); + public String getEnvironment() { + return environment; } /** - * Gets sha. + * Specifies if the given environment is specific to the deployment and will no longer exist at some point in the + * future. * - * @return the sha + * @return the environment is transient */ - public String getSha() { - return sha; + public boolean isTransientEnvironment() { + return transient_environment; } /** - * Gets statuses url. + * Specifies if the given environment is one that end-users directly interact with. * - * @return the statuses url + * @return the environment is used by end-users directly */ - public URL getStatusesUrl() { - return GitHubClient.parseURL(statusesUrl); + public boolean isProductionEnvironment() { + return production_environment; } /** - * Gets task. + * Gets creator. * - * @return the task + * @return the creator + * @throws IOException + * the io exception */ - public String getTask() { - return task; + public GHUser getCreator() throws IOException { + return root().intern(creator); } /** - * Specifies if the given environment is one that end-users directly interact with. + * Gets ref. * - * @return the environment is used by end-users directly + * @return the ref */ - public boolean isProductionEnvironment() { - return productionEnvironment; + public String getRef() { + return ref; } /** - * Specifies if the given environment is specific to the deployment and will no longer exist at some point in the - * future. + * Gets sha. * - * @return the environment is transient + * @return the sha */ - public boolean isTransientEnvironment() { - return transientEnvironment; + public String getSha() { + return sha; + } + + /** + * Create status gh deployment status builder. + * + * @param state + * the state + * @return the gh deployment status builder + */ + public GHDeploymentStatusBuilder createStatus(GHDeploymentState state) { + return new GHDeploymentStatusBuilder(owner, getId(), state); } /** @@ -197,7 +212,7 @@ public boolean isTransientEnvironment() { */ public PagedIterable listStatuses() { return root().createRequest() - .withUrlPath(statusesUrl) + .withUrlPath(statuses_url) .toIterable(GHDeploymentStatus[].class, item -> item.lateBind(owner)); } @@ -210,16 +225,4 @@ public PagedIterable listStatuses() { GHRepository getOwner() { return owner; } - - /** - * Wrap. - * - * @param owner - * the owner - * @return the GH deployment - */ - GHDeployment wrap(GHRepository owner) { - this.owner = owner; - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHDeploymentBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentBuilder.java index 3340558bbe..0463b425bc 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentBuilder.java @@ -11,8 +11,8 @@ */ // Based on https://developer.github.com/v3/repos/deployments/#create-a-deployment public class GHDeploymentBuilder { - private final Requester builder; private final GHRepository repo; + private final Requester builder; /** * Instantiates a new Gh deployment builder. @@ -40,53 +40,54 @@ public GHDeploymentBuilder(GHRepository repo, String ref) { } /** - * Auto merge gh deployment builder. + * Ref gh deployment builder. * - * @param autoMerge - * the auto merge + * @param branch + * the branch * * @return the gh deployment builder */ - public GHDeploymentBuilder autoMerge(boolean autoMerge) { - builder.with("auto_merge", autoMerge); + public GHDeploymentBuilder ref(String branch) { + builder.with("ref", branch); return this; } /** - * Create gh deployment. + * Task gh deployment builder. * - * @return the gh deployment + * @param task + * the task * - * @throws IOException - * the io exception + * @return the gh deployment builder */ - public GHDeployment create() throws IOException { - return builder.withUrlPath(repo.getApiTailUrl("deployments")).fetch(GHDeployment.class).wrap(repo); + public GHDeploymentBuilder task(String task) { + builder.with("task", task); + return this; } /** - * Description gh deployment builder. + * Auto merge gh deployment builder. * - * @param description - * the description + * @param autoMerge + * the auto merge * * @return the gh deployment builder */ - public GHDeploymentBuilder description(String description) { - builder.with("description", description); + public GHDeploymentBuilder autoMerge(boolean autoMerge) { + builder.with("auto_merge", autoMerge); return this; } /** - * Environment gh deployment builder. + * Required contexts gh deployment builder. * - * @param environment - * the environment + * @param requiredContexts + * the required contexts * * @return the gh deployment builder */ - public GHDeploymentBuilder environment(String environment) { - builder.with("environment", environment); + public GHDeploymentBuilder requiredContexts(List requiredContexts) { + builder.with("required_contexts", requiredContexts); return this; } @@ -104,66 +105,65 @@ public GHDeploymentBuilder payload(String payload) { } /** - * Specifies if the given environment is one that end-users directly interact with. + * Environment gh deployment builder. + * + * @param environment + * the environment * - * @param productionEnvironment - * the environment is used by end-users directly * @return the gh deployment builder */ - public GHDeploymentBuilder productionEnvironment(boolean productionEnvironment) { - builder.with("production_environment", productionEnvironment); + public GHDeploymentBuilder environment(String environment) { + builder.with("environment", environment); return this; } /** - * Ref gh deployment builder. - * - * @param branch - * the branch + * Specifies if the given environment is specific to the deployment and will no longer exist at some point in the + * future. * + * @param transientEnvironment + * the environment is transient * @return the gh deployment builder */ - public GHDeploymentBuilder ref(String branch) { - builder.with("ref", branch); + public GHDeploymentBuilder transientEnvironment(boolean transientEnvironment) { + builder.with("transient_environment", transientEnvironment); return this; } /** - * Required contexts gh deployment builder. - * - * @param requiredContexts - * the required contexts + * Specifies if the given environment is one that end-users directly interact with. * + * @param productionEnvironment + * the environment is used by end-users directly * @return the gh deployment builder */ - public GHDeploymentBuilder requiredContexts(List requiredContexts) { - builder.with("required_contexts", requiredContexts); + public GHDeploymentBuilder productionEnvironment(boolean productionEnvironment) { + builder.with("production_environment", productionEnvironment); return this; } /** - * Task gh deployment builder. + * Description gh deployment builder. * - * @param task - * the task + * @param description + * the description * * @return the gh deployment builder */ - public GHDeploymentBuilder task(String task) { - builder.with("task", task); + public GHDeploymentBuilder description(String description) { + builder.with("description", description); return this; } /** - * Specifies if the given environment is specific to the deployment and will no longer exist at some point in the - * future. + * Create gh deployment. * - * @param transientEnvironment - * the environment is transient - * @return the gh deployment builder + * @return the gh deployment + * + * @throws IOException + * the io exception */ - public GHDeploymentBuilder transientEnvironment(boolean transientEnvironment) { - builder.with("transient_environment", transientEnvironment); - return this; + public GHDeployment create() throws IOException { + return builder.withUrlPath(repo.getApiTailUrl("deployments")).fetch(GHDeployment.class).wrap(repo); } } diff --git a/src/main/java/org/kohsuke/github/GHDeploymentState.java b/src/main/java/org/kohsuke/github/GHDeploymentState.java index cefb3bc8ac..718e57c478 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentState.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentState.java @@ -6,30 +6,30 @@ */ public enum GHDeploymentState { + /** The pending. */ + PENDING, + + /** The success. */ + SUCCESS, + /** The error. */ ERROR, /** The failure. */ FAILURE, - /** - * The state of the deployment currently reflects it's no longer active. - */ - INACTIVE, - /** * The state of the deployment currently reflects it's in progress. */ IN_PROGRESS, - /** The pending. */ - PENDING, - /** * The state of the deployment currently reflects it's queued up for processing. */ QUEUED, - /** The success. */ - SUCCESS + /** + * The state of the deployment currently reflects it's no longer active. + */ + INACTIVE } diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatus.java b/src/main/java/org/kohsuke/github/GHDeploymentStatus.java index 3cf39fecf9..f48cd089ff 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatus.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatus.java @@ -9,36 +9,58 @@ */ public class GHDeploymentStatus extends GHObject { + /** + * Create default GHDeploymentStatus instance + */ + public GHDeploymentStatus() { + } + private GHRepository owner; /** The creator. */ protected GHUser creator; - /** The deployment url. */ - protected String deploymentUrl; + /** The state. */ + protected String state; /** The description. */ protected String description; - /** The environment url. */ - protected String environmentUrl; + /** The target url. */ + protected String target_url; /** The log url. */ - protected String logUrl; + protected String log_url; + + /** The deployment url. */ + protected String deployment_url; /** The repository url. */ - protected String repositoryUrl; + protected String repository_url; - /** The state. */ - protected String state; + /** The environment url. */ + protected String environment_url; - /** The target url. */ - protected String targetUrl; + /** + * Wrap gh deployment status. + * + * @param owner + * the owner + * + * @return the gh deployment status + */ + GHDeploymentStatus lateBind(GHRepository owner) { + this.owner = owner; + return this; + } /** - * Create default GHDeploymentStatus instance + * Gets target url. + * + * @return the target url */ - public GHDeploymentStatus() { + public URL getLogUrl() { + return GitHubClient.parseURL(log_url); } /** @@ -47,7 +69,7 @@ public GHDeploymentStatus() { * @return the deployment url */ public URL getDeploymentUrl() { - return GitHubClient.parseURL(deploymentUrl); + return GitHubClient.parseURL(deployment_url); } /** @@ -56,16 +78,7 @@ public URL getDeploymentUrl() { * @return the deployment environment url */ public URL getEnvironmentUrl() { - return GitHubClient.parseURL(environmentUrl); - } - - /** - * Gets target url. - * - * @return the target url - */ - public URL getLogUrl() { - return GitHubClient.parseURL(logUrl); + return GitHubClient.parseURL(environment_url); } /** @@ -74,7 +87,7 @@ public URL getLogUrl() { * @return the repository url */ public URL getRepositoryUrl() { - return GitHubClient.parseURL(repositoryUrl); + return GitHubClient.parseURL(repository_url); } /** @@ -95,17 +108,4 @@ public GHDeploymentState getState() { GHRepository getOwner() { return owner; } - - /** - * Wrap gh deployment status. - * - * @param owner - * the owner - * - * @return the gh deployment status - */ - GHDeploymentStatus lateBind(GHRepository owner) { - this.owner = owner; - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java index 23406e0580..e003758fb8 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java @@ -10,8 +10,8 @@ */ public class GHDeploymentStatusBuilder { private final Requester builder; - private long deploymentId; private GHRepository repo; + private long deploymentId; /** * Instantiates a new GH deployment status builder. @@ -44,20 +44,6 @@ public GHDeploymentStatusBuilder autoInactive(boolean autoInactive) { return this; } - /** - * Create gh deployment status. - * - * @return the gh deployment status - * - * @throws IOException - * the io exception - */ - public GHDeploymentStatus create() throws IOException { - return builder.withUrlPath(repo.getApiTailUrl("deployments/" + deploymentId + "/statuses")) - .fetch(GHDeploymentStatus.class) - .lateBind(repo); - } - /** * Description gh deployment status builder. * @@ -106,4 +92,18 @@ public GHDeploymentStatusBuilder logUrl(String logUrl) { this.builder.with("log_url", logUrl); return this; } + + /** + * Create gh deployment status. + * + * @return the gh deployment status + * + * @throws IOException + * the io exception + */ + public GHDeploymentStatus create() throws IOException { + return builder.withUrlPath(repo.getApiTailUrl("deployments/" + deploymentId + "/statuses")) + .fetch(GHDeploymentStatus.class) + .lateBind(repo); + } } diff --git a/src/main/java/org/kohsuke/github/GHDiscussion.java b/src/main/java/org/kohsuke/github/GHDiscussion.java index 99e8801d08..94edaacbc8 100644 --- a/src/main/java/org/kohsuke/github/GHDiscussion.java +++ b/src/main/java/org/kohsuke/github/GHDiscussion.java @@ -20,56 +20,98 @@ public class GHDiscussion extends GHObject { /** - * A {@link GHLabelBuilder} that creates a new {@link GHLabel} + * Create default GHDiscussion instance + */ + public GHDiscussion() { + } + + private GHTeam team; + private long number; + private String body, title, htmlUrl; + + @JsonProperty(value = "private") + private boolean isPrivate; + + /** + * Gets the html url. * - * Consumer must call {@link Creator#done()} to create the new instance. + * @return the html url + * @throws IOException + * Signals that an I/O exception has occurred. */ - public static class Creator extends GHDiscussionBuilder { + public URL getHtmlUrl() throws IOException { + return GitHubClient.parseURL(htmlUrl); + } - private Creator(@Nonnull GHTeam team) { - super(GHDiscussion.Creator.class, team, null); - requester.method("POST").setRawUrlPath(getRawUrlPath(team, null)); - } + /** + * Wrap up. + * + * @param team + * the team + * @return the GH discussion + */ + GHDiscussion wrapUp(GHTeam team) { + this.team = team; + return this; + } - /** - * Sets whether this discussion is private to this team. - * - * @param value - * privacy of this discussion - * @return either a continuing builder or an updated {@link GHDiscussion} - * @throws IOException - * if there is an I/O Exception - */ - @Nonnull - public Creator private_(boolean value) throws IOException { - return with("private", value); - } + /** + * Get the team to which this discussion belongs. + * + * @return the team for this discussion + */ + @Nonnull + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHTeam getTeam() { + return team; } /** - * A {@link GHLabelBuilder} that updates a single property per request + * Get the title of the discussion. * - * {@link GitHubRequestBuilderDone#done()} is called automatically after the property is set. + * @return the title */ - public static class Setter extends GHDiscussionBuilder { - private Setter(@Nonnull GHDiscussion base) { - super(GHDiscussion.class, base.team, base); - requester.method("PATCH").setRawUrlPath(base.getUrl().toString()); - } + public String getTitle() { + return title; } + /** - * A {@link GHLabelBuilder} that allows multiple properties to be updated per request. + * The description of this discussion. * - * Consumer must call {@link Updater#done()} to commit changes. + * @return the body */ - public static class Updater extends GHDiscussionBuilder { - private Updater(@Nonnull GHDiscussion base) { - super(GHDiscussion.Updater.class, base.team, base); - requester.method("PATCH").setRawUrlPath(base.getUrl().toString()); - } + public String getBody() { + return body; } - private static String getRawUrlPath(@Nonnull GHTeam team, @CheckForNull Long discussionNumber) { - return team.getUrl().toString() + "/discussions" + (discussionNumber == null ? "" : "/" + discussionNumber); + + /** + * The number of this discussion. + * + * @return the number + */ + public long getNumber() { + return number; + } + + /** + * The id number of this discussion. GitHub discussions have "number" instead of "id". This is provided for + * convenience. + * + * @return the id number for this discussion + * @see #getNumber() + */ + @Override + public long getId() { + return getNumber(); + } + + /** + * Whether the discussion is private to the team. + * + * @return {@code true} if discussion is private. + */ + public boolean isPrivate() { + return isPrivate; } /** @@ -80,8 +122,10 @@ private static String getRawUrlPath(@Nonnull GHTeam team, @CheckForNull Long dis * @param team * the team in which the discussion will be created. * @return a {@link GHLabel.Creator} + * @throws IOException + * the io exception */ - static GHDiscussion.Creator create(GHTeam team) { + static GHDiscussion.Creator create(GHTeam team) throws IOException { return new GHDiscussion.Creator(team); } @@ -110,27 +154,34 @@ static GHDiscussion read(GHTeam team, long discussionNumber) throws IOException * @param team * the team * @return the paged iterable + * @throws IOException + * Signals that an I/O exception has occurred. */ - static PagedIterable readAll(GHTeam team) { + static PagedIterable readAll(GHTeam team) throws IOException { return team.root() .createRequest() .setRawUrlPath(getRawUrlPath(team, null)) .toIterable(GHDiscussion[].class, item -> item.wrapUp(team)); } - private String body, title, htmlUrl; - - @JsonProperty(value = "private") - private boolean isPrivate; - - private long number; - - private GHTeam team; + /** + * Begins a batch update + * + * Consumer must call {@link GHDiscussion.Updater#done()} to commit changes. + * + * @return a {@link GHDiscussion.Updater} + */ + public GHDiscussion.Updater update() { + return new GHDiscussion.Updater(this); + } /** - * Create default GHDiscussion instance + * Begins a single property update. + * + * @return a {@link GHDiscussion.Setter} */ - public GHDiscussion() { + public GHDiscussion.Setter set() { + return new GHDiscussion.Setter(this); } /** @@ -143,83 +194,79 @@ public void delete() throws IOException { team.root().createRequest().method("DELETE").setRawUrlPath(getRawUrlPath(team, number)).send(); } - /** - * Equals. - * - * @param o - * the o - * @return true, if successful - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - GHDiscussion that = (GHDiscussion) o; - return number == that.number && Objects.equals(getUrl(), that.getUrl()) && Objects.equals(team, that.team) - && Objects.equals(body, that.body) && Objects.equals(title, that.title); + private static String getRawUrlPath(@Nonnull GHTeam team, @CheckForNull Long discussionNumber) { + return team.getUrl().toString() + "/discussions" + (discussionNumber == null ? "" : "/" + discussionNumber); } /** - * The description of this discussion. + * A {@link GHLabelBuilder} that updates a single property per request * - * @return the body + * {@link GitHubRequestBuilderDone#done()} is called automatically after the property is set. */ - public String getBody() { - return body; + public static class Setter extends GHDiscussionBuilder { + private Setter(@Nonnull GHDiscussion base) { + super(GHDiscussion.class, base.team, base); + requester.method("PATCH").setRawUrlPath(base.getUrl().toString()); + } } /** - * Gets the html url. + * A {@link GHLabelBuilder} that allows multiple properties to be updated per request. * - * @return the html url + * Consumer must call {@link Updater#done()} to commit changes. */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public static class Updater extends GHDiscussionBuilder { + private Updater(@Nonnull GHDiscussion base) { + super(GHDiscussion.Updater.class, base.team, base); + requester.method("PATCH").setRawUrlPath(base.getUrl().toString()); + } } /** - * The id number of this discussion. GitHub discussions have "number" instead of "id". This is provided for - * convenience. + * A {@link GHLabelBuilder} that creates a new {@link GHLabel} * - * @return the id number for this discussion - * @see #getNumber() + * Consumer must call {@link Creator#done()} to create the new instance. */ - @Override - public long getId() { - return getNumber(); - } + public static class Creator extends GHDiscussionBuilder { - /** - * The number of this discussion. - * - * @return the number - */ - public long getNumber() { - return number; - } + private Creator(@Nonnull GHTeam team) { + super(GHDiscussion.Creator.class, team, null); + requester.method("POST").setRawUrlPath(getRawUrlPath(team, null)); + } - /** - * Get the team to which this discussion belongs. - * - * @return the team for this discussion - */ - @Nonnull - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHTeam getTeam() { - return team; + /** + * Sets whether this discussion is private to this team. + * + * @param value + * privacy of this discussion + * @return either a continuing builder or an updated {@link GHDiscussion} + * @throws IOException + * if there is an I/O Exception + */ + @Nonnull + public Creator private_(boolean value) throws IOException { + return with("private", value); + } } /** - * Get the title of the discussion. + * Equals. * - * @return the title + * @param o + * the o + * @return true, if successful */ - public String getTitle() { - return title; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GHDiscussion that = (GHDiscussion) o; + return number == that.number && Objects.equals(getUrl(), that.getUrl()) && Objects.equals(team, that.team) + && Objects.equals(body, that.body) && Objects.equals(title, that.title); } /** @@ -231,45 +278,4 @@ public String getTitle() { public int hashCode() { return Objects.hash(team, number, body, title); } - - /** - * Whether the discussion is private to the team. - * - * @return {@code true} if discussion is private. - */ - public boolean isPrivate() { - return isPrivate; - } - - /** - * Begins a single property update. - * - * @return a {@link GHDiscussion.Setter} - */ - public GHDiscussion.Setter set() { - return new GHDiscussion.Setter(this); - } - - /** - * Begins a batch update - * - * Consumer must call {@link GHDiscussion.Updater#done()} to commit changes. - * - * @return a {@link GHDiscussion.Updater} - */ - public GHDiscussion.Updater update() { - return new GHDiscussion.Updater(this); - } - - /** - * Wrap up. - * - * @param team - * the team - * @return the GH discussion - */ - GHDiscussion wrapUp(GHTeam team) { - this.team = team; - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHDiscussionBuilder.java b/src/main/java/org/kohsuke/github/GHDiscussionBuilder.java index 30d1986731..19097c09fc 100644 --- a/src/main/java/org/kohsuke/github/GHDiscussionBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDiscussionBuilder.java @@ -10,7 +10,7 @@ * Base class for creating or updating a discussion. * * @param - * Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If {@code S} + * Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If {@link S} * the same as {@link GHLabel}, this builder will commit changes after each call to * {@link #with(String, Object)}. */ @@ -23,7 +23,7 @@ class GHDiscussionBuilder extends AbstractBuilder { * * @param intermediateReturnType * Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If - * {@code S} the same as {@link GHDiscussion}, this builder will commit changes after each call to + * {@link S} the same as {@link GHDiscussion}, this builder will commit changes after each call to * {@link #with(String, Object)}. * @param team * the GitHub team. Updates will be sent to the root of this team. @@ -43,6 +43,20 @@ protected GHDiscussionBuilder(@Nonnull Class intermediateReturnType, } } + /** + * Title for this discussion. + * + * @param value + * title of discussion + * @return either a continuing builder or an updated {@link GHDiscussion} + * @throws IOException + * if there is an I/O Exception + */ + @Nonnull + public S title(String value) throws IOException { + return with("title", value); + } + /** * Body content for this discussion. * @@ -65,18 +79,4 @@ public S body(String value) throws IOException { public GHDiscussion done() throws IOException { return super.done().wrapUp(team); } - - /** - * Title for this discussion. - * - * @param value - * title of discussion - * @return either a continuing builder or an updated {@link GHDiscussion} - * @throws IOException - * if there is an I/O Exception - */ - @Nonnull - public S title(String value) throws IOException { - return with("title", value); - } } diff --git a/src/main/java/org/kohsuke/github/GHEmail.java b/src/main/java/org/kohsuke/github/GHEmail.java index f5446a338d..75dcc0b6ba 100644 --- a/src/main/java/org/kohsuke/github/GHEmail.java +++ b/src/main/java/org/kohsuke/github/GHEmail.java @@ -37,6 +37,12 @@ justification = "JSON API") public class GHEmail { + /** + * Create default GHEmail instance + */ + public GHEmail() { + } + /** The email. */ protected String email; @@ -46,28 +52,6 @@ public class GHEmail { /** The verified. */ protected boolean verified; - /** - * Create default GHEmail instance - */ - public GHEmail() { - } - - /** - * Equals. - * - * @param obj - * the obj - * @return true, if successful - */ - @Override - public boolean equals(Object obj) { - if (obj instanceof GHEmail) { - GHEmail that = (GHEmail) obj; - return this.email.equals(that.email); - } - return false; - } - /** * Gets email. * @@ -77,16 +61,6 @@ public String getEmail() { return email; } - /** - * Hash code. - * - * @return the int - */ - @Override - public int hashCode() { - return email.hashCode(); - } - /** * Is primary boolean. * @@ -114,4 +88,30 @@ public boolean isVerified() { public String toString() { return "Email:" + email; } + + /** + * Hash code. + * + * @return the int + */ + @Override + public int hashCode() { + return email.hashCode(); + } + + /** + * Equals. + * + * @param obj + * the obj + * @return true, if successful + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof GHEmail) { + GHEmail that = (GHEmail) obj; + return this.email.equals(that.email); + } + return false; + } } diff --git a/src/main/java/org/kohsuke/github/GHError.java b/src/main/java/org/kohsuke/github/GHError.java index 3602703945..9455ff31fe 100644 --- a/src/main/java/org/kohsuke/github/GHError.java +++ b/src/main/java/org/kohsuke/github/GHError.java @@ -13,28 +13,37 @@ */ public class GHError implements Serializable { + /** + * Create default GHError instance + */ + public GHError() { + } + /** * The serial version UID of the error */ private static final long serialVersionUID = 2008071901; /** - * The URL to the documentation for the error. + * The error message. */ - @JsonProperty("documentation_url") @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private String documentation; + private String message; /** - * The error message. + * The URL to the documentation for the error. */ + @JsonProperty("documentation_url") @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private String message; + private String documentation; /** - * Create default GHError instance + * Get the error message. + * + * @return the message */ - public GHError() { + public String getMessage() { + return message; } /** @@ -46,13 +55,4 @@ public URL getDocumentationUrl() { return GitHubClient.parseURL(documentation); } - /** - * Get the error message. - * - * @return the message - */ - public String getMessage() { - return message; - } - } diff --git a/src/main/java/org/kohsuke/github/GHEvent.java b/src/main/java/org/kohsuke/github/GHEvent.java index d3619c06a0..1170743ac3 100644 --- a/src/main/java/org/kohsuke/github/GHEvent.java +++ b/src/main/java/org/kohsuke/github/GHEvent.java @@ -12,9 +12,6 @@ */ public enum GHEvent { - /** Special event type that means "every possible event". */ - ALL, - /** The branch protection rule. */ BRANCH_PROTECTION_RULE, @@ -39,15 +36,15 @@ public enum GHEvent { /** The delete. */ DELETE, + /** The deploy key. */ + DEPLOY_KEY, + /** The deployment. */ DEPLOYMENT, /** The deployment status. */ DEPLOYMENT_STATUS, - /** The deploy key. */ - DEPLOY_KEY, - /** The discussion. */ DISCUSSION, @@ -66,12 +63,12 @@ public enum GHEvent { /** The fork apply. */ FORK_APPLY, - /** The gist. */ - GIST, - /** The github app authorization. */ GITHUB_APP_AUTHORIZATION, + /** The gist. */ + GIST, + /** The gollum. */ GOLLUM, @@ -84,12 +81,12 @@ public enum GHEvent { /** The integration installation repositories. */ INTEGRATION_INSTALLATION_REPOSITORIES, - /** The issues. */ - ISSUES, - /** The issue comment. */ ISSUE_COMMENT, + /** The issues. */ + ISSUES, + /** The label. */ LABEL, @@ -102,12 +99,12 @@ public enum GHEvent { /** The membership. */ MEMBERSHIP, - /** The merge group entry. */ - MERGE_GROUP, - /** The merge queue entry. */ MERGE_QUEUE_ENTRY, + /** The merge group entry. */ + MERGE_GROUP, + /** The meta. */ META, @@ -126,18 +123,18 @@ public enum GHEvent { /** The page build. */ PAGE_BUILD, - /** The ping. */ - PING, - - /** The project. */ - PROJECT, - /** The project card. */ PROJECT_CARD, /** The project column. */ PROJECT_COLUMN, + /** The project. */ + PROJECT, + + /** The ping. */ + PING, + /** The public. */ PUBLIC, @@ -161,12 +158,12 @@ public enum GHEvent { /** The release. */ RELEASE, - /** The repository. */ - // only valid for org hooks - REPOSITORY, /** The repository dispatch. */ REPOSITORY_DISPATCH, + /** The repository. */ + // only valid for org hooks + REPOSITORY, /** The repository import. */ REPOSITORY_IMPORT, @@ -192,22 +189,25 @@ public enum GHEvent { /** The team add. */ TEAM_ADD, - /** - * Special event type that means we haven't found an enum value corresponding to the event. - */ - UNKNOWN, - /** The watch. */ WATCH, - /** The workflow dispatch. */ - WORKFLOW_DISPATCH, - /** The workflow job. */ WORKFLOW_JOB, + /** The workflow dispatch. */ + WORKFLOW_DISPATCH, + /** The workflow run. */ - WORKFLOW_RUN; + WORKFLOW_RUN, + + /** + * Special event type that means we haven't found an enum value corresponding to the event. + */ + UNKNOWN, + + /** Special event type that means "every possible event". */ + ALL; /** * Returns GitHub's internal representation of this event. diff --git a/src/main/java/org/kohsuke/github/GHEventInfo.java b/src/main/java/org/kohsuke/github/GHEventInfo.java index b9adccf2e6..551b6cb2ed 100644 --- a/src/main/java/org/kohsuke/github/GHEventInfo.java +++ b/src/main/java/org/kohsuke/github/GHEventInfo.java @@ -1,11 +1,9 @@ package org.kohsuke.github; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; -import java.time.Instant; import java.util.*; // TODO: Auto-generated Javadoc @@ -17,6 +15,34 @@ @SuppressFBWarnings(value = "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", justification = "JSON API") public class GHEventInfo extends GitHubInteractiveObject { + /** + * Create default GHEventInfo instance + */ + public GHEventInfo() { + } + + // we don't want to expose Jackson dependency to the user. This needs databinding + private ObjectNode payload; + + private long id; + private String created_at; + + /** + * Representation of GitHub Event API Event Type. + * + * This is not the same as the values used for hook methods such as + * {@link GHRepository#createHook(String, Map, Collection, boolean)}. + * + * @see GitHub event + * types + */ + private String type; + + // these are all shallow objects + private GHEventRepository repo; + private GHUser actor; + private GHOrganization org; + /** * Inside the event JSON model, GitHub uses a slightly different format. */ @@ -26,17 +52,17 @@ public class GHEventInfo extends GitHubInteractiveObject { justification = "JSON API") public static class GHEventRepository { - @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") - private long id; - - private String name; // owner/repo - @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") - private String url; // repository API URL /** * Create default GHEventRepository instance */ public GHEventRepository() { } + + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") + private long id; + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") + private String url; // repository API URL + private String name; // owner/repo } /** The Constant mapTypeStringToEvent. */ @@ -67,6 +93,7 @@ private static Map createEventMap() { map.put("WatchEvent", GHEvent.WATCH); return Collections.unmodifiableMap(map); } + /** * Transform type to GH event. * @@ -78,33 +105,44 @@ static GHEvent transformTypeToGHEvent(String type) { return mapTypeStringToEvent.getOrDefault(type, GHEvent.UNKNOWN); } - private GHUser actor; - - private String createdAt; - private long id; - private GHOrganization org; - - // we don't want to expose Jackson dependency to the user. This needs databinding - private ObjectNode payload; - - // these are all shallow objects - private GHEventRepository repo; + /** + * Gets type. + * + * @return the type + */ + public GHEvent getType() { + return transformTypeToGHEvent(type); + } /** - * Representation of GitHub Event API Event Type. + * Gets id. * - * This is not the same as the values used for hook methods such as - * {@link GHRepository#createHook(String, Map, Collection, boolean)}. + * @return the id + */ + public long getId() { + return id; + } + + /** + * Gets created at. * - * @see GitHub event - * types + * @return the created at */ - private String type; + public Date getCreatedAt() { + return GitHubClient.parseDate(created_at); + } /** - * Create default GHEventInfo instance + * Gets repository. + * + * @return Repository where the change was made. + * @throws IOException + * on error */ - public GHEventInfo() { + @SuppressFBWarnings(value = { "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" }, + justification = "The field comes from JSON deserialization") + public GHRepository getRepository() throws IOException { + return root().getRepository(repo.name); } /** @@ -124,30 +162,13 @@ public GHUser getActor() throws IOException { * Gets actor login. * * @return the login of the actor. + * @throws IOException + * on error */ - public String getActorLogin() { + public String getActorLogin() throws IOException { return actor.getLogin(); } - /** - * Gets created at. - * - * @return the created at - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCreatedAt() { - return GitHubClient.parseInstant(createdAt); - } - - /** - * Gets id. - * - * @return the id - */ - public long getId() { - return id; - } - /** * Gets organization. * @@ -178,26 +199,4 @@ public T getPayload(Class type) throws IOException v.lateBind(); return v; } - - /** - * Gets repository. - * - * @return Repository where the change was made. - * @throws IOException - * on error - */ - @SuppressFBWarnings(value = { "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" }, - justification = "The field comes from JSON deserialization") - public GHRepository getRepository() throws IOException { - return root().getRepository(repo.name); - } - - /** - * Gets type. - * - * @return the type - */ - public GHEvent getType() { - return transformTypeToGHEvent(type); - } } diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index d4d0af2b77..f0ca02c703 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -2,12 +2,10 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.io.Reader; -import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -25,6 +23,84 @@ */ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") public abstract class GHEventPayload extends GitHubInteractiveObject { + // https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#webhook-payload-object-common-properties + // Webhook payload object common properties: action, sender, repository, organization, installation + private String action; + private GHUser sender; + private GHRepository repository; + private GHOrganization organization; + private GHAppInstallation installation; + + /** + * Instantiates a new GH event payload. + */ + GHEventPayload() { + } + + /** + * Gets the action for the triggered event. Most but not all webhook payloads contain an action property that + * contains the specific activity that triggered the event. + * + * @return event action + */ + public String getAction() { + return action; + } + + /** + * Gets the sender or {@code null} if accessed via the events API. + * + * @return the sender or {@code null} if accessed via the events API. + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHUser getSender() { + return sender; + } + + /** + * Gets repository. + * + * @return the repository + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHRepository getRepository() { + return repository; + } + + /** + * Gets organization. + * + * @return the organization + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHOrganization getOrganization() { + return organization; + } + + /** + * Gets installation. + * + * @return the installation + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHAppInstallation getInstallation() { + return installation; + } + + // List of events that still need to be added: + // ContentReferenceEvent + // DeployKeyEvent DownloadEvent FollowEvent ForkApplyEvent GitHubAppAuthorizationEvent GistEvent GollumEvent + // InstallationEvent InstallationRepositoriesEvent IssuesEvent LabelEvent MarketplacePurchaseEvent MemberEvent + // MembershipEvent MetaEvent OrganizationEvent OrgBlockEvent PackageEvent PageBuildEvent + // ProjectCardEvent ProjectColumnEvent ProjectEvent RepositoryDispatchEvent RepositoryImportEvent + // RepositoryVulnerabilityAlertEvent SecurityAdvisoryEvent StarEvent StatusEvent TeamEvent TeamAddEvent WatchEvent + + /** + * Late bind. + */ + void lateBind() { + } + /** * A check run event has been created, rerequested, completed, or has a requested_action. * @@ -34,14 +110,23 @@ public abstract class GHEventPayload extends GitHubInteractiveObject { */ public static class CheckRun extends GHEventPayload { - private GHCheckRun checkRun; + /** + * Create default CheckRun instance + */ + public CheckRun() { + } private int number; + private GHCheckRun checkRun; private GHRequestedAction requestedAction; + /** - * Create default CheckRun instance + * Gets number. + * + * @return the number */ - public CheckRun() { + public int getNumber() { + return number; } /** @@ -54,15 +139,6 @@ public GHCheckRun getCheckRun() { return checkRun; } - /** - * Gets number. - * - * @return the number - */ - public int getNumber() { - return number; - } - /** * Gets the Requested Action object. * @@ -90,6 +166,7 @@ void lateBind() { } } } + /** * A check suite event has been requested, rerequested or completed. * @@ -99,14 +176,14 @@ void lateBind() { */ public static class CheckSuite extends GHEventPayload { - private GHCheckSuite checkSuite; - /** * Create default CheckSuite instance */ public CheckSuite() { } + private GHCheckSuite checkSuite; + /** * Gets the Check Suite object. * @@ -134,81 +211,62 @@ void lateBind() { } } } + /** - * Wrapper for changes on issue and pull request review comments action="edited". + * An installation has been installed, uninstalled, or its permissions have been changed. * - * @see GHEventPayload.IssueComment - * @see GHEventPayload.PullRequestReviewComment + * @see + * installation event + * @see GitHub App Installation */ - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "JSON API") - public static class CommentChanges { + public static class Installation extends GHEventPayload { /** - * Wrapper for changed values. + * Create default Installation instance */ - public static class GHFrom { - - private String from; - - /** - * Create default GHFrom instance - */ - public GHFrom() { - } - - /** - * Previous comment value that was changed. - * - * @return previous value - */ - public String getFrom() { - return from; - } + public Installation() { } - private GHFrom body; - - /** - * Create default CommentChanges instance - */ - public CommentChanges() { - } + private List repositories; + private List ghRepositories = null; /** - * Gets the previous comment body. + * Gets repositories. For the "deleted" action please rather call {@link #getRawRepositories()} * - * @return previous comment body (or null if not changed) + * @return the repositories */ - public GHFrom getBody() { - return body; - } - } - /** - * A comment was added to a commit. - * - * @see - * commit comment - * @see Comments - */ - public static class CommitComment extends GHEventPayload { + public List getRepositories() { + if ("deleted".equalsIgnoreCase(getAction())) { + throw new IllegalStateException("Can't call #getRepositories() on Installation event " + + "with 'deleted' action. Call #getRawRepositories() instead."); + } - private GHCommitComment comment; + if (ghRepositories == null) { + ghRepositories = new ArrayList<>(repositories.size()); + try { + for (Repository singleRepo : repositories) { + // populate each repository + // the repository information provided here is so limited + // as to be unusable without populating, so we do it eagerly + ghRepositories.add(this.root().getRepositoryById(singleRepo.getId())); + } + } catch (IOException e) { + throw new GHException("Failed to refresh repositories", e); + } + } - /** - * Create default CommitComment instance - */ - public CommitComment() { + return Collections.unmodifiableList(ghRepositories); } /** - * Gets comment. + * Returns a list of raw, unpopulated repositories. Useful when calling from within Installation event with + * action "deleted". You can't fetch the info for repositories of an already deleted installation. * - * @return the comment + * @return the list of raw Repository records */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHCommitComment getComment() { - return comment; + public List getRawRepositories() { + return Collections.unmodifiableList(repositories); } /** @@ -216,134 +274,125 @@ public GHCommitComment getComment() { */ @Override void lateBind() { - super.lateBind(); - GHRepository repository = getRepository(); - if (repository != null) { - comment.wrap(repository); + if (getInstallation() == null) { + throw new IllegalStateException( + "Expected installation payload, but got something else. Maybe we've got another type of event?"); } - } - } - /** - * A repository, branch, or tag was created. - * - * @see - * create event - * @see Git data - */ - public static class Create extends GHEventPayload { - - private String description; - - private String masterBranch; - private String ref; - private String refType; - /** - * Create default Create instance - */ - public Create() { + super.lateBind(); } /** - * Gets description. - * - * @return the description + * A special minimal implementation of a {@link GHRepository} which contains only fields from "Properties of + * repositories" from here */ - public String getDescription() { - return description; - } + public static class Repository { - /** - * Gets default branch. - * - * Name is an artifact of when "master" was the most common default. - * - * @return the default branch - */ - public String getMasterBranch() { - return masterBranch; - } + /** + * Create default Repository instance + */ + public Repository() { + } - /** - * Gets ref. - * - * @return the ref - */ - public String getRef() { - return ref; - } + private long id; + private String fullName; + private String name; + private String nodeId; + @JsonProperty(value = "private") + private boolean isPrivate; - /** - * Gets ref type. - * - * @return the ref type - */ - public String getRefType() { - return refType; + /** + * Get the id. + * + * @return the id + */ + public long getId() { + return id; + } + + /** + * Gets the full name. + * + * @return the full name + */ + public String getFullName() { + return fullName; + } + + /** + * Gets the name. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Gets the node id. + * + * @return the node id + */ + public String getNodeId() { + return nodeId; + } + + /** + * Gets the repository private flag. + * + * @return whether the repository is private + */ + public boolean isPrivate() { + return isPrivate; + } } } /** - * A branch, or tag was deleted. + * A repository has been added or removed from an installation. * - * @see - * delete event - * @see Git data + * @see + * installation_repositories event + * @see GitHub App installation */ - public static class Delete extends GHEventPayload { - - private String ref; + public static class InstallationRepositories extends GHEventPayload { - private String refType; /** - * Create default Delete instance + * Create default InstallationRepositories instance */ - public Delete() { + public InstallationRepositories() { } - /** - * Gets ref. - * - * @return the ref - */ - public String getRef() { - return ref; - } + private String repositorySelection; + private List repositoriesAdded; + private List repositoriesRemoved; /** - * Gets ref type. + * Gets installation selection. * - * @return the ref type + * @return the installation selection */ - public String getRefType() { - return refType; + public String getRepositorySelection() { + return repositorySelection; } - } - - /** - * A deployment. - * - * @see - * deployment event - * @see Deployments - */ - public static class Deployment extends GHEventPayload { - - private GHDeployment deployment; /** - * Create default Deployment instance + * Gets repositories added. + * + * @return the repositories */ - public Deployment() { + public List getRepositoriesAdded() { + return Collections.unmodifiableList(repositoriesAdded); } /** - * Gets deployment. + * Gets repositories removed. * - * @return the deployment + * @return the repositories */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHDeployment getDeployment() { - return deployment; + public List getRepositoriesRemoved() { + return Collections.unmodifiableList(repositoriesRemoved); } /** @@ -351,51 +400,88 @@ public GHDeployment getDeployment() { */ @Override void lateBind() { + if (getInstallation() == null) { + throw new IllegalStateException( + "Expected installation_repositories payload, but got something else. Maybe we've got another type of event?"); + } super.lateBind(); - GHRepository repository = getRepository(); - if (repository != null) { - deployment.wrap(repository); + List repositories; + if ("added".equals(getAction())) + repositories = repositoriesAdded; + else // action == "removed" + repositories = repositoriesRemoved; + + if (repositories != null && !repositories.isEmpty()) { + try { + for (GHRepository singleRepo : repositories) { // warp each of the repository + singleRepo.populate(); + } + } catch (IOException e) { + throw new GHException("Failed to refresh repositories", e); + } } } } /** - * A deployment status. + * A pull request status has changed. * * @see - * deployment_status event - * @see Deployments + * "https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#pull_request"> + * pull_request event + * @see Pull Requests */ - public static class DeploymentStatus extends GHEventPayload { + @SuppressFBWarnings(value = { "NP_UNWRITTEN_FIELD" }, justification = "JSON API") + public static class PullRequest extends GHEventPayload { - private GHDeployment deployment; + /** + * Create default PullRequest instance + */ + public PullRequest() { + } + + private int number; + private GHPullRequest pullRequest; + private GHLabel label; + private GHPullRequestChanges changes; - private GHDeploymentStatus deploymentStatus; /** - * Create default DeploymentStatus instance + * Gets number. + * + * @return the number */ - public DeploymentStatus() { + public int getNumber() { + return number; } /** - * Gets deployment. + * Gets pull request. * - * @return the deployment + * @return the pull request */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHDeployment getDeployment() { - return deployment; + public GHPullRequest getPullRequest() { + return pullRequest; } /** - * Gets deployment status. + * Gets the added or removed label for labeled/unlabeled events. * - * @return the deployment status + * @return label the added or removed label */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHDeploymentStatus getDeploymentStatus() { - return deploymentStatus; + public GHLabel getLabel() { + return label; + } + + /** + * Get changes (for action="edited"). + * + * @return changes + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHPullRequestChanges getChanges() { + return changes; } /** @@ -403,253 +489,172 @@ public GHDeploymentStatus getDeploymentStatus() { */ @Override void lateBind() { + if (pullRequest == null) + throw new IllegalStateException( + "Expected pull_request payload, but got something else. Maybe we've got another type of event?"); super.lateBind(); GHRepository repository = getRepository(); if (repository != null) { - deployment.wrap(repository); - deploymentStatus.lateBind(repository); + pullRequest.wrapUp(repository); } } } /** - * A discussion was closed, reopened, created, edited, deleted, pinned, unpinned, locked, unlocked, transferred, - * category_changed, answered, or unanswered. + * A review was added to a pull request. * * @see - * discussion event + * "https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review"> + * pull_request_review event + * @see Pull Request Reviews */ - public static class Discussion extends GHEventPayload { - - private GHRepositoryDiscussion discussion; - - private GHLabel label; + public static class PullRequestReview extends GHEventPayload { /** - * Create default Discussion instance + * Create default PullRequestReview instance */ - public Discussion() { + public PullRequestReview() { } + private GHPullRequestReview review; + private GHPullRequest pullRequest; + /** - * Gets discussion. + * Gets review. * - * @return the discussion + * @return the review */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHRepositoryDiscussion getDiscussion() { - return discussion; + public GHPullRequestReview getReview() { + return review; } /** - * Gets the added or removed label for labeled/unlabeled events. + * Gets pull request. * - * @return label the added or removed label + * @return the pull request */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHLabel getLabel() { - return label; + public GHPullRequest getPullRequest() { + return pullRequest; } - } - - /** - * A discussion comment was created, deleted, or edited. - * - * @see - * discussion event - */ - public static class DiscussionComment extends GHEventPayload { - - private GHRepositoryDiscussionComment comment; - - private GHRepositoryDiscussion discussion; /** - * Create default DiscussionComment instance + * Late bind. */ - public DiscussionComment() { - } + @Override + void lateBind() { + if (review == null) + throw new IllegalStateException( + "Expected pull_request_review payload, but got something else. Maybe we've got another type of event?"); + super.lateBind(); - /** - * Gets discussion comment. - * - * @return the discussion - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHRepositoryDiscussionComment getComment() { - return comment; - } + review.wrapUp(pullRequest); - /** - * Gets discussion. - * - * @return the discussion - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHRepositoryDiscussion getDiscussion() { - return discussion; + GHRepository repository = getRepository(); + if (repository != null) { + pullRequest.wrapUp(repository); + } } } /** - * A user forked a repository. + * Wrapper for changes on issue and pull request review comments action="edited". * - * @see fork - * event - * @see Forks + * @see GHEventPayload.IssueComment + * @see GHEventPayload.PullRequestReviewComment */ - public static class Fork extends GHEventPayload { - - private GHRepository forkee; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "JSON API") + public static class CommentChanges { /** - * Create default Fork instance + * Create default CommentChanges instance */ - public Fork() { + public CommentChanges() { } + private GHFrom body; + /** - * Gets forkee. + * Gets the previous comment body. * - * @return the forkee + * @return previous comment body (or null if not changed) */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHRepository getForkee() { - return forkee; + public GHFrom getBody() { + return body; } - } - - // List of events that still need to be added: - // ContentReferenceEvent - // DeployKeyEvent DownloadEvent FollowEvent ForkApplyEvent GitHubAppAuthorizationEvent GistEvent GollumEvent - // InstallationEvent InstallationRepositoriesEvent IssuesEvent LabelEvent MarketplacePurchaseEvent MemberEvent - // MembershipEvent MetaEvent MilestoneEvent OrganizationEvent OrgBlockEvent PackageEvent PageBuildEvent - // ProjectCardEvent ProjectColumnEvent ProjectEvent RepositoryDispatchEvent RepositoryImportEvent - // RepositoryVulnerabilityAlertEvent SecurityAdvisoryEvent StarEvent StatusEvent TeamEvent TeamAddEvent WatchEvent - - /** - * An installation has been installed, uninstalled, or its permissions have been changed. - * - * @see - * installation event - * @see GitHub App Installation - */ - public static class Installation extends GHEventPayload { /** - * A special minimal implementation of a {@link GHRepository} which contains only fields from "Properties of - * repositories" from here + * Wrapper for changed values. */ - public static class Repository { - - private String fullName; - - private long id; - @JsonProperty(value = "private") - private boolean isPrivate; - private String name; - private String nodeId; - /** - * Create default Repository instance - */ - public Repository() { - } + public static class GHFrom { /** - * Gets the full name. - * - * @return the full name + * Create default GHFrom instance */ - public String getFullName() { - return fullName; + public GHFrom() { } - /** - * Get the id. - * - * @return the id - */ - public long getId() { - return id; - } + private String from; /** - * Gets the name. + * Previous comment value that was changed. * - * @return the name + * @return previous value */ - public String getName() { - return name; + public String getFrom() { + return from; } + } + } - /** - * Gets the node id. - * - * @return the node id - */ - public String getNodeId() { - return nodeId; - } + /** + * A review comment was added to a pull request. + * + * @see + * pull_request_review_comment event + * @see Pull Request Review Comments + */ + public static class PullRequestReviewComment extends GHEventPayload { - /** - * Gets the repository private flag. - * - * @return whether the repository is private - */ - public boolean isPrivate() { - return isPrivate; - } + /** + * Create default PullRequestReviewComment instance + */ + public PullRequestReviewComment() { } - private List ghRepositories = null; - private List repositories; + private GHPullRequestReviewComment comment; + private GHPullRequest pullRequest; + private CommentChanges changes; /** - * Create default Installation instance + * Gets comment. + * + * @return the comment */ - public Installation() { + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHPullRequestReviewComment getComment() { + return comment; } /** - * Returns a list of raw, unpopulated repositories. Useful when calling from within Installation event with - * action "deleted". You can't fetch the info for repositories of an already deleted installation. + * Get changes (for action="edited"). * - * @return the list of raw Repository records + * @return changes */ - public List getRawRepositories() { - return Collections.unmodifiableList(repositories); + public CommentChanges getChanges() { + return changes; } /** - * Gets repositories. For the "deleted" action please rather call {@link #getRawRepositories()} + * Gets pull request. * - * @return the repositories + * @return the pull request */ - public List getRepositories() { - if ("deleted".equalsIgnoreCase(getAction())) { - throw new IllegalStateException("Can't call #getRepositories() on Installation event " - + "with 'deleted' action. Call #getRawRepositories() instead."); - } - - if (ghRepositories == null) { - ghRepositories = new ArrayList<>(repositories.size()); - try { - for (Repository singleRepo : repositories) { - // populate each repository - // the repository information provided here is so limited - // as to be unusable without populating, so we do it eagerly - ghRepositories.add(this.root().getRepositoryById(singleRepo.getId())); - } - } catch (IOException e) { - throw new GHException("Failed to refresh repositories", e); - } - } - - return Collections.unmodifiableList(ghRepositories); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHPullRequest getPullRequest() { + return pullRequest; } /** @@ -657,59 +662,69 @@ public List getRepositories() { */ @Override void lateBind() { - if (getInstallation() == null) { + if (comment == null) throw new IllegalStateException( - "Expected installation payload, but got something else. Maybe we've got another type of event?"); - } + "Expected pull_request_review_comment payload, but got something else. Maybe we've got another type of event?"); super.lateBind(); + comment.wrapUp(pullRequest); + + GHRepository repository = getRepository(); + if (repository != null) { + pullRequest.wrapUp(repository); + } } } /** - * A repository has been added or removed from an installation. + * A Issue has been assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or + * reopened. * - * @see - * installation_repositories event - * @see GitHub App installation + * @see + * issues events + * @see Issues Comments */ - public static class InstallationRepositories extends GHEventPayload { - - private List repositoriesAdded; + public static class Issue extends GHEventPayload { - private List repositoriesRemoved; - private String repositorySelection; /** - * Create default InstallationRepositories instance + * Create default Issue instance */ - public InstallationRepositories() { + public Issue() { } + private GHIssue issue; + + private GHLabel label; + + private GHIssueChanges changes; + /** - * Gets repositories added. + * Gets issue. * - * @return the repositories + * @return the issue */ - public List getRepositoriesAdded() { - return Collections.unmodifiableList(repositoriesAdded); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHIssue getIssue() { + return issue; } /** - * Gets repositories removed. + * Gets the added or removed label for labeled/unlabeled events. * - * @return the repositories + * @return label the added or removed label */ - public List getRepositoriesRemoved() { - return Collections.unmodifiableList(repositoriesRemoved); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHLabel getLabel() { + return label; } /** - * Gets installation selection. + * Get changes (for action="edited"). * - * @return the installation selection + * @return changes */ - public String getRepositorySelection() { - return repositorySelection; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHIssueChanges getChanges() { + return changes; } /** @@ -717,49 +732,42 @@ public String getRepositorySelection() { */ @Override void lateBind() { - if (getInstallation() == null) { - throw new IllegalStateException( - "Expected installation_repositories payload, but got something else. Maybe we've got another type of event?"); - } super.lateBind(); - List repositories; - if ("added".equals(getAction())) - repositories = repositoriesAdded; - else // action == "removed" - repositories = repositoriesRemoved; - - if (repositories != null && !repositories.isEmpty()) { - try { - for (GHRepository singleRepo : repositories) { // warp each of the repository - singleRepo.populate(); - } - } catch (IOException e) { - throw new GHException("Failed to refresh repositories", e); - } + GHRepository repository = getRepository(); + if (repository != null) { + issue.wrap(repository); } } } /** - * A Issue has been assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or - * reopened. + * A comment was added to an issue. * - * @see - * issues events - * @see Issues Comments + * @see + * issue_comment event + * @see Issue Comments */ - public static class Issue extends GHEventPayload { + public static class IssueComment extends GHEventPayload { - private GHIssueChanges changes; + /** + * Create default IssueComment instance + */ + public IssueComment() { + } + private GHIssueComment comment; private GHIssue issue; - - private GHLabel label; + private CommentChanges changes; /** - * Create default Issue instance + * Gets comment. + * + * @return the comment */ - public Issue() { + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHIssueComment getComment() { + return comment; } /** @@ -767,8 +775,7 @@ public Issue() { * * @return changes */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHIssueChanges getChanges() { + public CommentChanges getChanges() { return changes; } @@ -782,16 +789,6 @@ public GHIssue getIssue() { return issue; } - /** - * Gets the added or removed label for labeled/unlabeled events. - * - * @return label the added or removed label - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHLabel getLabel() { - return label; - } - /** * Late bind. */ @@ -802,37 +799,27 @@ void lateBind() { if (repository != null) { issue.wrap(repository); } + comment.wrapUp(issue); } } /** - * A comment was added to an issue. + * A comment was added to a commit. * * @see - * issue_comment event - * @see Issue Comments + * "https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#commit_comment"> + * commit comment + * @see Comments */ - public static class IssueComment extends GHEventPayload { - - private CommentChanges changes; + public static class CommitComment extends GHEventPayload { - private GHIssueComment comment; - private GHIssue issue; /** - * Create default IssueComment instance + * Create default CommitComment instance */ - public IssueComment() { + public CommitComment() { } - /** - * Get changes (for action="edited"). - * - * @return changes - */ - public CommentChanges getChanges() { - return changes; - } + private GHCommitComment comment; /** * Gets comment. @@ -840,20 +827,10 @@ public CommentChanges getChanges() { * @return the comment */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHIssueComment getComment() { + public GHCommitComment getComment() { return comment; } - /** - * Gets issue. - * - * @return the issue - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHIssue getIssue() { - return issue; - } - /** * Late bind. */ @@ -862,122 +839,132 @@ void lateBind() { super.lateBind(); GHRepository repository = getRepository(); if (repository != null) { - issue.wrap(repository); + comment.wrap(repository); } - comment.wrapUp(issue); } } /** - * A label was created, edited or deleted. + * A repository, branch, or tag was created. * - * @see - * label event + * @see + * create event + * @see Git data */ - public static class Label extends GHEventPayload { + public static class Create extends GHEventPayload { - private GHLabelChanges changes; + /** + * Create default Create instance + */ + public Create() { + } - private GHLabel label; + private String ref; + private String refType; + private String masterBranch; + private String description; /** - * Create default Label instance + * Gets ref. + * + * @return the ref */ - public Label() { + public String getRef() { + return ref; } /** - * Gets changes (for action="edited"). + * Gets ref type. * - * @return changes + * @return the ref type */ - public GHLabelChanges getChanges() { - return changes; + public String getRefType() { + return refType; } /** - * Gets the label. + * Gets default branch. * - * @return the label + * Name is an artifact of when "master" was the most common default. + * + * @return the default branch */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHLabel getLabel() { - return label; + public String getMasterBranch() { + return masterBranch; + } + + /** + * Gets description. + * + * @return the description + */ + public String getDescription() { + return description; } } /** - * A member event was triggered. + * A branch, or tag was deleted. * - * @see member event + * @see + * delete event + * @see Git data */ - public static class Member extends GHEventPayload { - - private GHMemberChanges changes; - - private GHUser member; + public static class Delete extends GHEventPayload { /** - * Create default Member instance + * Create default Delete instance */ - public Member() { + public Delete() { } + private String ref; + private String refType; + /** - * Gets the changes made to the member. + * Gets ref. * - * @return the changes made to the member + * @return the ref */ - public GHMemberChanges getChanges() { - return changes; + public String getRef() { + return ref; } /** - * Gets the member. + * Gets ref type. * - * @return the member + * @return the ref type */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHUser getMember() { - return member; + public String getRefType() { + return refType; } } /** - * A membership event was triggered. + * A deployment. * - * @see membership event + * @see + * deployment event + * @see Deployments */ - public static class Membership extends GHEventPayload { - - private GHUser member; - - private GHTeam team; + public static class Deployment extends GHEventPayload { /** - * Create default Membership instance + * Create default Deployment instance */ - public Membership() { + public Deployment() { } - /** - * Gets the member. - * - * @return the member - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHUser getMember() { - return member; - } + private GHDeployment deployment; /** - * Gets the team. + * Gets deployment. * - * @return the team + * @return the deployment */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHTeam getTeam() { - return team; + public GHDeployment getDeployment() { + return deployment; } /** @@ -985,71 +972,109 @@ public GHTeam getTeam() { */ @Override void lateBind() { - if (team == null) { - throw new IllegalStateException( - "Expected membership payload, but got something else. Maybe we've got another type of event?"); - } super.lateBind(); - GHOrganization organization = getOrganization(); - if (organization == null) { - throw new IllegalStateException("Organization must not be null"); + GHRepository repository = getRepository(); + if (repository != null) { + deployment.wrap(repository); } - team.wrapUp(organization); } } /** - * A ping. + * A deployment status. * - * ping - * event + * @see + * deployment_status event + * @see Deployments */ - public static class Ping extends GHEventPayload { + public static class DeploymentStatus extends GHEventPayload { /** - * Create default Ping instance + * Create default DeploymentStatus instance */ - public Ping() { + public DeploymentStatus() { + } + + private GHDeploymentStatus deploymentStatus; + private GHDeployment deployment; + + /** + * Gets deployment status. + * + * @return the deployment status + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHDeploymentStatus getDeploymentStatus() { + return deploymentStatus; + } + + /** + * Gets deployment. + * + * @return the deployment + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHDeployment getDeployment() { + return deployment; } + /** + * Late bind. + */ + @Override + void lateBind() { + super.lateBind(); + GHRepository repository = getRepository(); + if (repository != null) { + deployment.wrap(repository); + deploymentStatus.lateBind(repository); + } + } } /** - * A project v2 item was archived, converted, created, edited, restored, deleted, or reordered. + * A user forked a repository. * - * @see projects_v2_item + * @see fork * event + * @see Forks */ - public static class ProjectsV2Item extends GHEventPayload { - - private GHProjectsV2ItemChanges changes; + public static class Fork extends GHEventPayload { - private GHProjectsV2Item projectsV2Item; /** - * Create default ProjectsV2Item instance + * Create default Fork instance */ - public ProjectsV2Item() { + public Fork() { } + private GHRepository forkee; + /** - * Gets the changes. + * Gets forkee. * - * @return the changes + * @return the forkee */ - public GHProjectsV2ItemChanges getChanges() { - return changes; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHRepository getForkee() { + return forkee; } + } + + /** + * A ping. + * + * ping + * event + */ + public static class Ping extends GHEventPayload { /** - * Gets the projects V 2 item. - * - * @return the projects V 2 item + * Create default Ping instance */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHProjectsV2Item getProjectsV2Item() { - return projectsV2Item; + public Ping() { } + } /** @@ -1069,240 +1094,183 @@ public Public() { } /** - * A pull request status has changed. + * A commit was pushed. * - * @see - * pull_request event - * @see Pull Requests + * @see push + * event */ - @SuppressFBWarnings(value = { "NP_UNWRITTEN_FIELD" }, justification = "JSON API") - public static class PullRequest extends GHEventPayload { - - private GHPullRequestChanges changes; + public static class Push extends GHEventPayload { - private GHLabel label; - private int number; - private GHPullRequest pullRequest; /** - * Create default PullRequest instance + * Create default Push instance */ - public PullRequest() { + public Push() { } + private String head, before; + private boolean created, deleted, forced; + private String ref; + private int size; + private List commits; + private PushCommit headCommit; + private Pusher pusher; + private String compare; + /** - * Get changes (for action="edited"). + * The SHA of the HEAD commit on the repository. * - * @return changes + * @return the head */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHPullRequestChanges getChanges() { - return changes; + public String getHead() { + return head; } /** - * Gets the added or removed label for labeled/unlabeled events. + * This is undocumented, but it looks like this captures the commit that the ref was pointing to before the + * push. * - * @return label the added or removed label + * @return the before */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHLabel getLabel() { - return label; + public String getBefore() { + return before; + } + + @JsonSetter // alias + private void setAfter(String after) { + head = after; } /** - * Gets number. + * The full Git ref that was pushed. Example: “refs/heads/main” * - * @return the number + * @return the ref */ - public int getNumber() { - return number; + public String getRef() { + return ref; } /** - * Gets pull request. + * The number of commits in the push. Is this always the same as {@code getCommits().size()}? * - * @return the pull request + * @return the size */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHPullRequest getPullRequest() { - return pullRequest; + public int getSize() { + return size; } /** - * Late bind. + * Is created boolean. + * + * @return the boolean */ - @Override - void lateBind() { - if (pullRequest == null) - throw new IllegalStateException( - "Expected pull_request payload, but got something else. Maybe we've got another type of event?"); - super.lateBind(); - GHRepository repository = getRepository(); - if (repository != null) { - pullRequest.wrapUp(repository); - } + public boolean isCreated() { + return created; } - } - /** - * A review was added to a pull request. - * - * @see - * pull_request_review event - * @see Pull Request Reviews - */ - public static class PullRequestReview extends GHEventPayload { + /** + * Is deleted boolean. + * + * @return the boolean + */ + public boolean isDeleted() { + return deleted; + } - private GHPullRequest pullRequest; + /** + * Is forced boolean. + * + * @return the boolean + */ + public boolean isForced() { + return forced; + } - private GHPullRequestReview review; /** - * Create default PullRequestReview instance + * The list of pushed commits. + * + * @return the commits */ - public PullRequestReview() { + public List getCommits() { + return Collections.unmodifiableList(commits); } /** - * Gets pull request. + * The head commit of the push. * - * @return the pull request + * @return the commit */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHPullRequest getPullRequest() { - return pullRequest; + public PushCommit getHeadCommit() { + return headCommit; } /** - * Gets review. + * Gets pusher. * - * @return the review + * @return the pusher */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHPullRequestReview getReview() { - return review; + public Pusher getPusher() { + return pusher; } /** - * Late bind. + * Gets compare. + * + * @return compare */ - @Override - void lateBind() { - if (review == null) - throw new IllegalStateException( - "Expected pull_request_review payload, but got something else. Maybe we've got another type of event?"); - super.lateBind(); + public String getCompare() { + return compare; + } - review.wrapUp(pullRequest); + /** + * The type Pusher. + */ + public static class Pusher { - GHRepository repository = getRepository(); - if (repository != null) { - pullRequest.wrapUp(repository); + /** + * Create default Pusher instance + */ + public Pusher() { } - } - } - /** - * A review comment was added to a pull request. - * - * @see - * pull_request_review_comment event - * @see Pull Request Review Comments - */ - public static class PullRequestReviewComment extends GHEventPayload { - - private CommentChanges changes; - - private GHPullRequestReviewComment comment; - private GHPullRequest pullRequest; - /** - * Create default PullRequestReviewComment instance - */ - public PullRequestReviewComment() { - } - - /** - * Get changes (for action="edited"). - * - * @return changes - */ - public CommentChanges getChanges() { - return changes; - } - - /** - * Gets comment. - * - * @return the comment - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHPullRequestReviewComment getComment() { - return comment; - } - - /** - * Gets pull request. - * - * @return the pull request - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHPullRequest getPullRequest() { - return pullRequest; - } + private String name, email; - /** - * Late bind. - */ - @Override - void lateBind() { - if (comment == null) - throw new IllegalStateException( - "Expected pull_request_review_comment payload, but got something else. Maybe we've got another type of event?"); - super.lateBind(); - comment.wrapUp(pullRequest); + /** + * Gets name. + * + * @return the name + */ + public String getName() { + return name; + } - GHRepository repository = getRepository(); - if (repository != null) { - pullRequest.wrapUp(repository); + /** + * Gets email. + * + * @return the email + */ + public String getEmail() { + return email; } } - } - - /** - * A commit was pushed. - * - * @see push - * event - */ - public static class Push extends GHEventPayload { /** * Commit in a push. Note: sha is an alias for id. */ public static class PushCommit { - private List added, removed, modified; - - private GitUser author; - private GitUser committer; - private boolean distinct; - private String url, sha, message, timestamp; /** * Create default PushCommit instance */ public PushCommit() { } - /** - * Gets added. - * - * @return the added - */ - public List getAdded() { - return Collections.unmodifiableList(added); - } + private GitUser author; + private GitUser committer; + private String url, sha, message, timestamp; + private boolean distinct; + private List added, removed, modified; /** * Gets author. @@ -1322,6 +1290,29 @@ public GitUser getCommitter() { return committer; } + /** + * Points to the commit API resource. + * + * @return the url + */ + public String getUrl() { + return url; + } + + /** + * Gets sha (id). + * + * @return the sha + */ + public String getSha() { + return sha; + } + + @JsonSetter + private void setId(String id) { + sha = id; + } + /** * Gets message. * @@ -1332,12 +1323,21 @@ public String getMessage() { } /** - * Gets modified. + * Whether this commit is distinct from any that have been pushed before. * - * @return the modified + * @return the boolean */ - public List getModified() { - return Collections.unmodifiableList(modified); + public boolean isDistinct() { + return distinct; + } + + /** + * Gets added. + * + * @return the added + */ + public List getAdded() { + return Collections.unmodifiableList(added); } /** @@ -1350,12 +1350,12 @@ public List getRemoved() { } /** - * Gets sha (id). + * Gets modified. * - * @return the sha + * @return the modified */ - public String getSha() { - return sha; + public List getModified() { + return Collections.unmodifiableList(modified); } /** @@ -1363,247 +1363,428 @@ public String getSha() { * * @return the timestamp */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getTimestamp() { - return GitHubClient.parseInstant(timestamp); + public Date getTimestamp() { + return GitHubClient.parseDate(timestamp); } + } + } - /** - * Points to the commit API resource. - * - * @return the url - */ - public String getUrl() { - return url; - } + /** + * A release was added to the repo. + * + * @see + * release event + * @see Releases + */ + @SuppressFBWarnings(value = { "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class Release extends GHEventPayload { - /** - * Whether this commit is distinct from any that have been pushed before. - * - * @return the boolean - */ - public boolean isDistinct() { - return distinct; - } + /** + * Create default Release instance + */ + public Release() { + } - @JsonSetter - private void setId(String id) { - sha = id; - } + private GHRelease release; + /** + * Gets release. + * + * @return the release + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHRelease getRelease() { + return release; } + } + + /** + * A repository was created, deleted, made public, or made private. + * + * @see + * repository event + * @see Repositories + */ + public static class Repository extends GHEventPayload { /** - * The type Pusher. + * Create default Repository instance */ - public static class Pusher { + public Repository() { + } - private String name, email; + private GHRepositoryChanges changes; - /** - * Create default Pusher instance - */ - public Pusher() { - } + /** + * Get changes. + * + * @return GHRepositoryChanges + */ + public GHRepositoryChanges getChanges() { + return changes; + } - /** - * Gets email. - * - * @return the email - */ - public String getEmail() { - return email; + } + + /** + * A git commit status was changed. + * + * @see + * status event + * @see Repository Statuses + */ + public static class Status extends GHEventPayload { + + /** + * Create default Status instance + */ + public Status() { + } + + private String context; + private String description; + private GHCommitState state; + private GHCommit commit; + private String targetUrl; + + /** + * Gets the status content. + * + * @return status content + */ + public String getContext() { + return context; + } + + /** + * The optional link added to the status. + * + * @return a url + */ + public String getTargetUrl() { + return targetUrl; + } + + /** + * Gets the status description. + * + * @return status description + */ + public String getDescription() { + return description; + } + + /** + * Gets the status state. + * + * @return status state + */ + public GHCommitState getState() { + return state; + } + + /** + * Gets the commit associated with the status event. + * + * @return commit + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHCommit getCommit() { + return commit; + } + + /** + * Late bind. + */ + @Override + void lateBind() { + + if (state == null) { + throw new IllegalStateException( + "Expected status payload, but got something else. Maybe we've got another type of event?"); } + super.lateBind(); - /** - * Gets name. - * - * @return the name - */ - public String getName() { - return name; + GHRepository repository = getRepository(); + if (repository != null) { + commit.wrapUp(repository); } } - private List commits; - private String compare; - private boolean created, deleted, forced; - private String head, before; - private PushCommit headCommit; - private Pusher pusher; - private String ref; + } - private int size; + /** + * Occurs when someone triggered a workflow run or sends a POST request to the "Create a workflow dispatch event" + * endpoint. + * + * @see + * workflow dispatch event + * @see Events that + * trigger workflows + */ + public static class WorkflowDispatch extends GHEventPayload { /** - * Create default Push instance + * Create default WorkflowDispatch instance */ - public Push() { + public WorkflowDispatch() { } + private Map inputs; + private String ref; + private String workflow; + /** - * This is undocumented, but it looks like this captures the commit that the ref was pointing to before the - * push. + * Gets the map of input parameters passed to the workflow. * - * @return the before + * @return the map of input parameters */ - public String getBefore() { - return before; + public Map getInputs() { + return Collections.unmodifiableMap(inputs); } /** - * The list of pushed commits. + * Gets the ref of the branch (e.g. refs/heads/main) * - * @return the commits + * @return the ref of the branch */ - public List getCommits() { - return Collections.unmodifiableList(commits); + public String getRef() { + return ref; } /** - * Gets compare. + * Gets the path of the workflow file (e.g. .github/workflows/hello-world-workflow.yml). * - * @return compare + * @return the path of the workflow file */ - public String getCompare() { - return compare; + public String getWorkflow() { + return workflow; } + } + + /** + * A workflow run was requested or completed. + * + * @see + * workflow run event + * @see Actions Workflow Runs + */ + public static class WorkflowRun extends GHEventPayload { /** - * The SHA of the HEAD commit on the repository. - * - * @return the head + * Create default WorkflowRun instance */ - public String getHead() { - return head; + public WorkflowRun() { } + private GHWorkflowRun workflowRun; + private GHWorkflow workflow; + /** - * The head commit of the push. + * Gets the workflow run. * - * @return the commit + * @return the workflow run */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public PushCommit getHeadCommit() { - return headCommit; + public GHWorkflowRun getWorkflowRun() { + return workflowRun; } /** - * Gets pusher. + * Gets the associated workflow. * - * @return the pusher + * @return the associated workflow + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHWorkflow getWorkflow() { + return workflow; + } + + /** + * Late bind. + */ + @Override + void lateBind() { + if (workflowRun == null || workflow == null) { + throw new IllegalStateException( + "Expected workflow and workflow_run payload, but got something else. Maybe we've got another type of event?"); + } + super.lateBind(); + GHRepository repository = getRepository(); + if (repository == null) { + throw new IllegalStateException("Repository must not be null"); + } + workflowRun.wrapUp(repository); + workflow.wrapUp(repository); + } + } + + /** + * A workflow job has been queued, is in progress, or has been completed. + * + * @see + * workflow job event + * @see Actions Workflow Jobs + */ + public static class WorkflowJob extends GHEventPayload { + + /** + * Create default WorkflowJob instance */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public Pusher getPusher() { - return pusher; + public WorkflowJob() { } + private GHWorkflowJob workflowJob; + /** - * The full Git ref that was pushed. Example: “refs/heads/main” + * Gets the workflow job. * - * @return the ref + * @return the workflow job */ - public String getRef() { - return ref; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHWorkflowJob getWorkflowJob() { + return workflowJob; } /** - * The number of commits in the push. Is this always the same as {@code getCommits().size()}? - * - * @return the size + * Late bind. */ - public int getSize() { - return size; + @Override + void lateBind() { + if (workflowJob == null) { + throw new IllegalStateException( + "Expected workflow_job payload, but got something else. Maybe we've got another type of event?"); + } + super.lateBind(); + GHRepository repository = getRepository(); + if (repository == null) { + throw new IllegalStateException("Repository must not be null"); + } + workflowJob.wrapUp(repository); } + } + + /** + * A label was created, edited or deleted. + * + * @see + * label event + */ + public static class Label extends GHEventPayload { /** - * Is created boolean. - * - * @return the boolean + * Create default Label instance */ - public boolean isCreated() { - return created; + public Label() { } + private GHLabel label; + + private GHLabelChanges changes; + /** - * Is deleted boolean. + * Gets the label. * - * @return the boolean + * @return the label */ - public boolean isDeleted() { - return deleted; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHLabel getLabel() { + return label; } /** - * Is forced boolean. + * Gets changes (for action="edited"). * - * @return the boolean + * @return changes */ - public boolean isForced() { - return forced; - } - - @JsonSetter // alias - private void setAfter(String after) { - head = after; + public GHLabelChanges getChanges() { + return changes; } } /** - * A release was added to the repo. + * A discussion was closed, reopened, created, edited, deleted, pinned, unpinned, locked, unlocked, transferred, + * category_changed, answered, or unanswered. * - * @see - * release event - * @see Releases + * @see + * discussion event */ - @SuppressFBWarnings(value = { "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, - justification = "Constructed by JSON deserialization") - public static class Release extends GHEventPayload { + public static class Discussion extends GHEventPayload { - private GHRelease release; + /** + * Create default Discussion instance + */ + public Discussion() { + } + + private GHRepositoryDiscussion discussion; + + private GHLabel label; /** - * Create default Release instance + * Gets discussion. + * + * @return the discussion */ - public Release() { + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHRepositoryDiscussion getDiscussion() { + return discussion; } /** - * Gets release. + * Gets the added or removed label for labeled/unlabeled events. * - * @return the release + * @return label the added or removed label */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHRelease getRelease() { - return release; + public GHLabel getLabel() { + return label; } } /** - * A repository was created, deleted, made public, or made private. + * A discussion comment was created, deleted, or edited. * - * @see - * repository event - * @see Repositories + * @see + * discussion event */ - public static class Repository extends GHEventPayload { - - private GHRepositoryChanges changes; + public static class DiscussionComment extends GHEventPayload { /** - * Create default Repository instance + * Create default DiscussionComment instance */ - public Repository() { + public DiscussionComment() { } + private GHRepositoryDiscussion discussion; + + private GHRepositoryDiscussionComment comment; + /** - * Get changes. + * Gets discussion. * - * @return GHRepositoryChanges + * @return the discussion */ - public GHRepositoryChanges getChanges() { - return changes; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHRepositoryDiscussion getDiscussion() { + return discussion; } + /** + * Gets discussion comment. + * + * @return the discussion + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHRepositoryDiscussionComment getComment() { + return comment; + } } /** @@ -1615,137 +1796,77 @@ public GHRepositoryChanges getChanges() { */ public static class Star extends GHEventPayload { - private String starredAt; - /** * Create default Star instance */ public Star() { } + private String starredAt; + /** * Gets the date when the star is added. Is null when the star is deleted. * * @return the date when the star is added */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getStarredAt() { - return GitHubClient.parseInstant(starredAt); + public Date getStarredAt() { + return GitHubClient.parseDate(starredAt); } } /** - * A git commit status was changed. + * A project v2 item was archived, converted, created, edited, restored, deleted, or reordered. * - * @see - * status event - * @see Repository Statuses + * @see projects_v2_item + * event */ - public static class Status extends GHEventPayload { - - private GHCommit commit; - - private String context; - private String description; - private GHCommitState state; - private String targetUrl; - /** - * Create default Status instance - */ - public Status() { - } - - /** - * Gets the commit associated with the status event. - * - * @return commit - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHCommit getCommit() { - return commit; - } + public static class ProjectsV2Item extends GHEventPayload { /** - * Gets the status content. - * - * @return status content + * Create default ProjectsV2Item instance */ - public String getContext() { - return context; + public ProjectsV2Item() { } - /** - * Gets the status description. - * - * @return status description - */ - public String getDescription() { - return description; - } + private GHProjectsV2Item projectsV2Item; + private GHProjectsV2ItemChanges changes; /** - * Gets the status state. + * Gets the projects V 2 item. * - * @return status state + * @return the projects V 2 item */ - public GHCommitState getState() { - return state; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHProjectsV2Item getProjectsV2Item() { + return projectsV2Item; } /** - * The optional link added to the status. + * Gets the changes. * - * @return a url - */ - public String getTargetUrl() { - return targetUrl; - } - - /** - * Late bind. - */ - @Override - void lateBind() { - - if (state == null) { - throw new IllegalStateException( - "Expected status payload, but got something else. Maybe we've got another type of event?"); - } - super.lateBind(); - - GHRepository repository = getRepository(); - if (repository != null) { - commit.wrapUp(repository); - } - } - } - - /** - * A team event was triggered. - * - * @see team event - */ - public static class Team extends GHEventPayload { - - private GHTeamChanges changes; - - private GHTeam team; - - /** - * Create default Team instance + * @return the changes */ - public Team() { + public GHProjectsV2ItemChanges getChanges() { + return changes; } + } + + /** + * A team_add event was triggered. + * + * @see team_add event + */ + public static class TeamAdd extends GHEventPayload { /** - * Gets the changes made to the team. - * - * @return the changes made to the team, null unless action is "edited". + * Create default TeamAdd instance */ - public GHTeamChanges getChanges() { - return changes; + public TeamAdd() { } + private GHTeam team; + /** * Gets the team. * @@ -1775,20 +1896,22 @@ void lateBind() { } /** - * A team_add event was triggered. + * A team event was triggered. * - * @see team_add event + * @see team event */ - public static class TeamAdd extends GHEventPayload { - - private GHTeam team; + public static class Team extends GHEventPayload { /** - * Create default TeamAdd instance + * Create default Team instance */ - public TeamAdd() { + public Team() { } + private GHTeam team; + + private GHTeamChanges changes; + /** * Gets the team. * @@ -1799,6 +1922,15 @@ public GHTeam getTeam() { return team; } + /** + * Gets the changes made to the team. + * + * @return the changes made to the team, null unless action is "edited". + */ + public GHTeamChanges getChanges() { + return changes; + } + /** * Late bind. */ @@ -1818,82 +1950,77 @@ void lateBind() { } /** - * Occurs when someone triggered a workflow run or sends a POST request to the "Create a workflow dispatch event" - * endpoint. + * A member event was triggered. * - * @see - * workflow dispatch event - * @see Events that - * trigger workflows + * @see member event */ - public static class WorkflowDispatch extends GHEventPayload { - - private Map inputs; + public static class Member extends GHEventPayload { - private String ref; - private String workflow; /** - * Create default WorkflowDispatch instance + * Create default Member instance */ - public WorkflowDispatch() { + public Member() { } - /** - * Gets the map of input parameters passed to the workflow. - * - * @return the map of input parameters - */ - public Map getInputs() { - return Collections.unmodifiableMap(inputs); - } + private GHUser member; + + private GHMemberChanges changes; /** - * Gets the ref of the branch (e.g. refs/heads/main) + * Gets the member. * - * @return the ref of the branch + * @return the member */ - public String getRef() { - return ref; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHUser getMember() { + return member; } /** - * Gets the path of the workflow file (e.g. .github/workflows/hello-world-workflow.yml). + * Gets the changes made to the member. * - * @return the path of the workflow file + * @return the changes made to the member */ - public String getWorkflow() { - return workflow; + public GHMemberChanges getChanges() { + return changes; } } /** - * A workflow job has been queued, is in progress, or has been completed. + * A membership event was triggered. * - * @see - * workflow job event - * @see Actions Workflow Jobs + * @see membership event */ - public static class WorkflowJob extends GHEventPayload { + public static class Membership extends GHEventPayload { - private GHWorkflowJob workflowJob; + /** + * Create default Membership instance + */ + public Membership() { + } + + private GHTeam team; + + private GHUser member; /** - * Create default WorkflowJob instance + * Gets the team. + * + * @return the team */ - public WorkflowJob() { + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHTeam getTeam() { + return team; } /** - * Gets the workflow job. + * Gets the member. * - * @return the workflow job + * @return the member */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHWorkflowJob getWorkflowJob() { - return workflowJob; + public GHUser getMember() { + return member; } /** @@ -1901,148 +2028,42 @@ public GHWorkflowJob getWorkflowJob() { */ @Override void lateBind() { - if (workflowJob == null) { + if (team == null) { throw new IllegalStateException( - "Expected workflow_job payload, but got something else. Maybe we've got another type of event?"); + "Expected membership payload, but got something else. Maybe we've got another type of event?"); } super.lateBind(); - GHRepository repository = getRepository(); - if (repository == null) { - throw new IllegalStateException("Repository must not be null"); + GHOrganization organization = getOrganization(); + if (organization == null) { + throw new IllegalStateException("Organization must not be null"); } - workflowJob.wrapUp(repository); + team.wrapUp(organization); } } /** - * A workflow run was requested or completed. + * A milestone event was triggered. * - * @see - * workflow run event - * @see Actions Workflow Runs + * @see milestone event */ - public static class WorkflowRun extends GHEventPayload { - - private GHWorkflow workflow; + public static class Milestone extends GHEventPayload { - private GHWorkflowRun workflowRun; /** - * Create default WorkflowRun instance + * Create default Milestone instance */ - public WorkflowRun() { + public Milestone() { } - /** - * Gets the associated workflow. - * - * @return the associated workflow - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHWorkflow getWorkflow() { - return workflow; - } + private GHMilestone milestone; /** - * Gets the workflow run. + * Gets the milestone. * - * @return the workflow run + * @return the milestone */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHWorkflowRun getWorkflowRun() { - return workflowRun; - } - - /** - * Late bind. - */ - @Override - void lateBind() { - if (workflowRun == null || workflow == null) { - throw new IllegalStateException( - "Expected workflow and workflow_run payload, but got something else. Maybe we've got another type of event?"); - } - super.lateBind(); - GHRepository repository = getRepository(); - if (repository == null) { - throw new IllegalStateException("Repository must not be null"); - } - workflowRun.wrapUp(repository); - workflow.wrapUp(repository); + public GHMilestone getMilestone() { + return milestone; } } - - // https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#webhook-payload-object-common-properties - // Webhook payload object common properties: action, sender, repository, organization, installation - private String action; - - private GHAppInstallation installation; - - private GHOrganization organization; - - private GHRepository repository; - - private GHUser sender; - - /** - * Instantiates a new GH event payload. - */ - GHEventPayload() { - } - - /** - * Gets the action for the triggered event. Most but not all webhook payloads contain an action property that - * contains the specific activity that triggered the event. - * - * @return event action - */ - public String getAction() { - return action; - } - - /** - * Gets installation. - * - * @return the installation - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHAppInstallation getInstallation() { - return installation; - } - - /** - * Gets organization. - * - * @return the organization - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHOrganization getOrganization() { - return organization; - } - - /** - * Gets repository. - * - * @return the repository - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHRepository getRepository() { - return repository; - } - - /** - * Gets the sender or {@code null} if accessed via the events API. - * - * @return the sender or {@code null} if accessed via the events API. - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHUser getSender() { - return sender; - } - - /** - * Late bind. - */ - void lateBind() { - } } diff --git a/src/main/java/org/kohsuke/github/GHExternalGroup.java b/src/main/java/org/kohsuke/github/GHExternalGroup.java index f5fb69a78d..01d997b628 100644 --- a/src/main/java/org/kohsuke/github/GHExternalGroup.java +++ b/src/main/java/org/kohsuke/github/GHExternalGroup.java @@ -1,10 +1,8 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; -import java.time.Instant; import java.util.Collections; import java.util.Date; import java.util.List; @@ -16,16 +14,61 @@ */ public class GHExternalGroup extends GitHubInteractiveObject implements Refreshable { + /** + * A reference of a team linked to an external group + * + * @author Miguel Esteban Gutiérrez + */ + public static class GHLinkedTeam { + + /** + * Create default GHLinkedTeam instance + */ + public GHLinkedTeam() { + } + + /** + * The identifier of the team + */ + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private long teamId; + + /** + * The name of the team + */ + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private String teamName; + + /** + * Get the linked team identifier + * + * @return the id + */ + public long getId() { + return teamId; + } + + /** + * Get the linked team name + * + * @return the name + */ + public String getName() { + return teamName; + } + + } + /** * A reference of an external member linked to an external group */ public static class GHLinkedExternalMember { /** - * The email attached to the user + * Create default GHLinkedExternalMember instance */ - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private String memberEmail; + public GHLinkedExternalMember() { + } /** * The internal user ID of the identity @@ -46,19 +89,10 @@ public static class GHLinkedExternalMember { private String memberName; /** - * Create default GHLinkedExternalMember instance - */ - public GHLinkedExternalMember() { - } - - /** - * Get the linked member email - * - * @return the email + * The email attached to the user */ - public String getEmail() { - return memberEmail; - } + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private String memberEmail; /** * Get the linked member identifier @@ -87,49 +121,13 @@ public String getName() { return memberName; } - } - - /** - * A reference of a team linked to an external group - * - * @author Miguel Esteban Gutiérrez - */ - public static class GHLinkedTeam { - - /** - * The identifier of the team - */ - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private long teamId; - - /** - * The name of the team - */ - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private String teamName; - - /** - * Create default GHLinkedTeam instance - */ - public GHLinkedTeam() { - } - /** - * Get the linked team identifier - * - * @return the id - */ - public long getId() { - return teamId; - } - - /** - * Get the linked team name + * Get the linked member email * - * @return the name + * @return the email */ - public String getName() { - return teamName; + public String getEmail() { + return memberEmail; } } @@ -147,12 +145,10 @@ public String getName() { private String groupName; /** - * The external members linked to this group + * The date when the group was last updated at */ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private List members; - - private GHOrganization organization; + private String updatedAt; /** * The teams linked to this group @@ -161,32 +157,58 @@ public String getName() { private List teams; /** - * The date when the group was last updated at + * The external members linked to this group */ @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private String updatedAt; + private List members; GHExternalGroup() { this.teams = Collections.emptyList(); this.members = Collections.emptyList(); } + private GHOrganization organization; + /** - * Get the external group id. + * Wrap up. * - * @return the id + * @param owner + * the owner */ - public long getId() { - return groupId; + GHExternalGroup wrapUp(final GHOrganization owner) { + this.organization = owner; + return this; } /** - * Get the external members linked to this group. + * Wrap up. * - * @return the external members + * @param root + * the root */ - public List getMembers() { - return Collections.unmodifiableList(members); + void wrapUp(final GitHub root) { // auto-wrapUp when organization is known from GET /orgs/{org}/external-groups + wrapUp(organization); + } + + /** + * Gets organization. + * + * @return the organization + * @throws IOException + * the io exception + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHOrganization getOrganization() throws IOException { + return organization; + } + + /** + * Get the external group id. + * + * @return the id + */ + public long getId() { + return groupId; } /** @@ -199,13 +221,12 @@ public String getName() { } /** - * Gets organization. + * Get the external group last update date. * - * @return the organization + * @return the date */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHOrganization getOrganization() { - return organization; + public Date getUpdatedAt() { + return GitHubClient.parseDate(updatedAt); } /** @@ -218,13 +239,12 @@ public List getTeams() { } /** - * Get the external group last update date. + * Get the external members linked to this group. * - * @return the date + * @return the external members */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getUpdatedAt() { - return GitHubClient.parseInstant(updatedAt); + public List getMembers() { + return Collections.unmodifiableList(members); } /** @@ -242,25 +262,4 @@ private String api(final String tail) { return "/orgs/" + organization.getLogin() + "/external-group/" + getId() + tail; } - /** - * Wrap up. - * - * @param owner - * the owner - */ - GHExternalGroup wrapUp(final GHOrganization owner) { - this.organization = owner; - return this; - } - - /** - * Wrap up. - * - * @param root - * the root - */ - void wrapUp(final GitHub root) { // auto-wrapUp when organization is known from GET /orgs/{org}/external-groups - wrapUp(organization); - } - } diff --git a/src/main/java/org/kohsuke/github/GHFork.java b/src/main/java/org/kohsuke/github/GHFork.java index 620cab32e0..34434e137f 100644 --- a/src/main/java/org/kohsuke/github/GHFork.java +++ b/src/main/java/org/kohsuke/github/GHFork.java @@ -7,18 +7,18 @@ public enum GHFork { /** - * Search only in forks with more stars than the parent repository. + * Search in the parent repository and in forks with more stars than the parent repository. * - * The parent repository is ignored. If no forks have more stars than the parent, no results will be returned. + * Forks with the same or fewer stars than the parent repository are still ignored. */ - FORKS_ONLY("only"), + PARENT_AND_FORKS("true"), /** - * Search in the parent repository and in forks with more stars than the parent repository. + * Search only in forks with more stars than the parent repository. * - * Forks with the same or fewer stars than the parent repository are still ignored. + * The parent repository is ignored. If no forks have more stars than the parent, no results will be returned. */ - PARENT_AND_FORKS("true"), + FORKS_ONLY("only"), /** * (Default) Search only the parent repository. diff --git a/src/main/java/org/kohsuke/github/GHGist.java b/src/main/java/org/kohsuke/github/GHGist.java index e7c4042f5b..d035ee6ef6 100644 --- a/src/main/java/org/kohsuke/github/GHGist.java +++ b/src/main/java/org/kohsuke/github/GHGist.java @@ -23,21 +23,21 @@ */ public class GHGist extends GHObject { - private int comments; + /** The owner. */ + final GHUser owner; + + private String forks_url, commits_url, id, git_pull_url, git_push_url, html_url; - private String commentsUrl; + @JsonProperty("public") + private boolean _public; private String description; - private final Map files; + private int comments; - private String forksUrl, commitsUrl, id, gitPullUrl, gitPushUrl, htmlUrl; + private String comments_url; - @JsonProperty("public") - private boolean isPublic; - - /** The owner. */ - final GHUser owner; + private final Map files; @JsonCreator private GHGist(@JsonProperty("owner") GHUser owner, @JsonProperty("files") Map files) { @@ -49,60 +49,48 @@ private GHGist(@JsonProperty("owner") GHUser owner, @JsonProperty("files") Map getFiles() { - return Collections.unmodifiableMap(files); + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); } /** - * Gets forks url. + * Is public boolean. * - * @return the forks url + * @return the boolean */ - public String getForksUrl() { - return forksUrl; + public boolean isPublic() { + return _public; } /** - * Gets the id for this Gist. Unlike most other GitHub objects, the id for Gists can be non-numeric, such as - * "aa5a315d61ae9438b18d". This should be used instead of {@link #getId()}. + * Gets description. * - * @return id of this Gist + * @return the description */ - public String getGistId() { - return this.id; + public String getDescription() { + return description; } /** - * Gets git pull url. + * Gets comment count. * - * @return URL like https://gist.github.com/gists/12345.git + * @return the comment count */ - public String getGitPullUrl() { - return gitPullUrl; + public int getCommentCount() { + return comments; } /** - * Gets git push url. + * Gets comments url. * - * @return the git push url + * @return API URL of listing comments. */ - public String getGitPushUrl() { - return gitPushUrl; + public String getCommentsUrl() { + return comments_url; } /** - * Get the html url. + * Gets file. * - * @return the github html url + * @param name + * the name + * @return the file */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public GHGistFile getFile(String name) { + return files.get(name); } /** - * Unlike most other GitHub objects, the id for Gists can be non-numeric, such as "aa5a315d61ae9438b18d". If the id - * is numeric, this method will get it. If id is not numeric, this will throw a runtime - * {@link NumberFormatException}. + * Gets files. * - * @return id of the Gist. - * @deprecated Use {@link #getGistId()} instead. + * @return the files */ - @Deprecated - @Override - public long getId() { - return Long.parseLong(getGistId()); + public Map getFiles() { + return Collections.unmodifiableMap(files); } /** - * Gets owner. + * Gets the api tail url. * - * @return User that owns this Gist. + * @param tail + * the tail + * @return the api tail url */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getOwner() { - return owner; + String getApiTailUrl(String tail) { + String result = "/gists/" + id; + if (!StringUtils.isBlank(tail)) { + result += StringUtils.prependIfMissing(tail, "/"); + } + return result; } /** - * Hash code. + * Star. * - * @return the int + * @throws IOException + * the io exception */ - @Override - public int hashCode() { - return id.hashCode(); + public void star() throws IOException { + root().createRequest().method("PUT").withUrlPath(getApiTailUrl("star")).send(); } /** - * Is public boolean. + * Unstar. * - * @return the boolean + * @throws IOException + * the io exception */ - public boolean isPublic() { - return isPublic; + public void unstar() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiTailUrl("star")).send(); } /** @@ -243,6 +231,17 @@ public boolean isStarred() throws IOException { return root().createRequest().withUrlPath(getApiTailUrl("star")).fetchHttpStatusCode() / 100 == 2; } + /** + * Forks this gist into your own. + * + * @return the gh gist + * @throws IOException + * the io exception + */ + public GHGist fork() throws IOException { + return root().createRequest().method("POST").withUrlPath(getApiTailUrl("forks")).fetch(GHGist.class); + } + /** * List forks paged iterable. * @@ -253,46 +252,51 @@ public PagedIterable listForks() { } /** - * Star. + * Deletes this gist. * * @throws IOException * the io exception */ - public void star() throws IOException { - root().createRequest().method("PUT").withUrlPath(getApiTailUrl("star")).send(); + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath("/gists/" + id).send(); } /** - * Unstar. + * Updates this gist via a builder. * + * @return the gh gist updater * @throws IOException * the io exception */ - public void unstar() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiTailUrl("star")).send(); + public GHGistUpdater update() throws IOException { + return new GHGistUpdater(this); } /** - * Updates this gist via a builder. + * Equals. * - * @return the gh gist updater + * @param o + * the o + * @return true, if successful */ - public GHGistUpdater update() { - return new GHGistUpdater(this); + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + GHGist ghGist = (GHGist) o; + return id.equals(ghGist.id); + } /** - * Gets the api tail url. + * Hash code. * - * @param tail - * the tail - * @return the api tail url + * @return the int */ - String getApiTailUrl(String tail) { - String result = "/gists/" + id; - if (!StringUtils.isBlank(tail)) { - result += StringUtils.prependIfMissing(tail, "/"); - } - return result; + @Override + public int hashCode() { + return id.hashCode(); } } diff --git a/src/main/java/org/kohsuke/github/GHGistBuilder.java b/src/main/java/org/kohsuke/github/GHGistBuilder.java index 5d7cb908d9..c2797b628c 100644 --- a/src/main/java/org/kohsuke/github/GHGistBuilder.java +++ b/src/main/java/org/kohsuke/github/GHGistBuilder.java @@ -14,8 +14,8 @@ * @see GitHub#createGist() GitHub#createGist() */ public class GHGistBuilder { - private final LinkedHashMap files = new LinkedHashMap(); private final Requester req; + private final LinkedHashMap files = new LinkedHashMap(); /** * Instantiates a new Gh gist builder. @@ -27,18 +27,6 @@ public GHGistBuilder(GitHub root) { req = root.createRequest().method("POST"); } - /** - * Creates a Gist based on the parameters specified thus far. - * - * @return created Gist - * @throws IOException - * if Gist cannot be created. - */ - public GHGist create() throws IOException { - req.with("files", files); - return req.withUrlPath("/gists").fetch(GHGist.class); - } - /** * Description gh gist builder. * @@ -51,6 +39,18 @@ public GHGistBuilder description(String desc) { return this; } + /** + * Public gh gist builder. + * + * @param v + * the v + * @return the gh gist builder + */ + public GHGistBuilder public_(boolean v) { + req.with("public", v); + return this; + } + /** * File gh gist builder. * @@ -66,14 +66,14 @@ public GHGistBuilder file(@Nonnull String fileName, @Nonnull String content) { } /** - * Public gh gist builder. + * Creates a Gist based on the parameters specified thus far. * - * @param v - * the v - * @return the gh gist builder + * @return created Gist + * @throws IOException + * if Gist cannot be created. */ - public GHGistBuilder public_(boolean v) { - req.with("public", v); - return this; + public GHGist create() throws IOException { + req.with("files", files); + return req.withUrlPath("/gists").fetch(GHGist.class); } } diff --git a/src/main/java/org/kohsuke/github/GHGistFile.java b/src/main/java/org/kohsuke/github/GHGistFile.java index da60cc902d..8a4b8f48e5 100644 --- a/src/main/java/org/kohsuke/github/GHGistFile.java +++ b/src/main/java/org/kohsuke/github/GHGistFile.java @@ -10,27 +10,18 @@ */ public class GHGistFile { - private String rawUrl, type, language, content; - - private int size; - - private boolean truncated; - /** The file name. */ - /* package almost final */ String fileName; /** * Create default GHGistFile instance */ public GHGistFile() { } - /** - * Content of this file. - * - * @return the content - */ - public String getContent() { - return content; - } + /** The file name. */ + /* package almost final */ String fileName; + + private int size; + private String raw_url, type, language, content; + private boolean truncated; /** * Gets file name. @@ -42,12 +33,12 @@ public String getFileName() { } /** - * Gets language. + * File size in bytes. * - * @return the language + * @return the size */ - public String getLanguage() { - return language; + public int getSize() { + return size; } /** @@ -56,25 +47,34 @@ public String getLanguage() { * @return the raw url */ public String getRawUrl() { - return rawUrl; + return raw_url; } /** - * File size in bytes. + * Content type of this Gist, such as "text/plain". * - * @return the size + * @return the type */ - public int getSize() { - return size; + public String getType() { + return type; } /** - * Content type of this Gist, such as "text/plain". + * Gets language. * - * @return the type + * @return the language */ - public String getType() { - return type; + public String getLanguage() { + return language; + } + + /** + * Content of this file. + * + * @return the content + */ + public String getContent() { + return content; } /** diff --git a/src/main/java/org/kohsuke/github/GHGistUpdater.java b/src/main/java/org/kohsuke/github/GHGistUpdater.java index cc67de6f89..5faaccde4d 100644 --- a/src/main/java/org/kohsuke/github/GHGistUpdater.java +++ b/src/main/java/org/kohsuke/github/GHGistUpdater.java @@ -41,8 +41,10 @@ public class GHGistUpdater { * @param content * the content * @return the gh gist updater + * @throws IOException + * the io exception */ - public GHGistUpdater addFile(@Nonnull String fileName, @Nonnull String content) { + public GHGistUpdater addFile(@Nonnull String fileName, @Nonnull String content) throws IOException { updateFile(fileName, content); return this; } @@ -53,24 +55,14 @@ public GHGistUpdater addFile(@Nonnull String fileName, @Nonnull String content) * @param fileName * the file name * @return the GH gist updater + * @throws IOException + * Signals that an I/O exception has occurred. */ - public GHGistUpdater deleteFile(@Nonnull String fileName) { + public GHGistUpdater deleteFile(@Nonnull String fileName) throws IOException { files.put(fileName, null); return this; } - /** - * Description gh gist updater. - * - * @param desc - * the desc - * @return the gh gist updater - */ - public GHGistUpdater description(String desc) { - builder.with("description", desc); - return this; - } - /** * Rename file gh gist updater. * @@ -79,25 +71,15 @@ public GHGistUpdater description(String desc) { * @param newFileName * the new file name * @return the gh gist updater + * @throws IOException + * the io exception */ - public GHGistUpdater renameFile(@Nonnull String fileName, @Nonnull String newFileName) { + public GHGistUpdater renameFile(@Nonnull String fileName, @Nonnull String newFileName) throws IOException { Map file = files.computeIfAbsent(fileName, d -> new HashMap<>()); file.put("filename", newFileName); return this; } - /** - * Updates the Gist based on the parameters specified thus far. - * - * @return the gh gist - * @throws IOException - * the io exception - */ - public GHGist update() throws IOException { - builder.with("files", files); - return builder.method("PATCH").withUrlPath(base.getApiTailUrl("")).fetch(GHGist.class); - } - /** * Update file gh gist updater. * @@ -106,8 +88,10 @@ public GHGist update() throws IOException { * @param content * the content * @return the gh gist updater + * @throws IOException + * the io exception */ - public GHGistUpdater updateFile(@Nonnull String fileName, @Nonnull String content) { + public GHGistUpdater updateFile(@Nonnull String fileName, @Nonnull String content) throws IOException { Map file = files.computeIfAbsent(fileName, d -> new HashMap<>()); file.put("content", content); return this; @@ -123,12 +107,39 @@ public GHGistUpdater updateFile(@Nonnull String fileName, @Nonnull String conten * @param content * the content * @return the gh gist updater + * @throws IOException + * the io exception */ - public GHGistUpdater updateFile(@Nonnull String fileName, @Nonnull String newFileName, @Nonnull String content) { + public GHGistUpdater updateFile(@Nonnull String fileName, @Nonnull String newFileName, @Nonnull String content) + throws IOException { Map file = files.computeIfAbsent(fileName, d -> new HashMap<>()); file.put("content", content); file.put("filename", newFileName); files.put(fileName, file); return this; } + + /** + * Description gh gist updater. + * + * @param desc + * the desc + * @return the gh gist updater + */ + public GHGistUpdater description(String desc) { + builder.with("description", desc); + return this; + } + + /** + * Updates the Gist based on the parameters specified thus far. + * + * @return the gh gist + * @throws IOException + * the io exception + */ + public GHGist update() throws IOException { + builder.with("files", files); + return builder.method("PATCH").withUrlPath(base.getApiTailUrl("")).fetch(GHGist.class); + } } diff --git a/src/main/java/org/kohsuke/github/GHHook.java b/src/main/java/org/kohsuke/github/GHHook.java index cc41288b7f..d9e1fc3bd4 100644 --- a/src/main/java/org/kohsuke/github/GHHook.java +++ b/src/main/java/org/kohsuke/github/GHHook.java @@ -19,41 +19,31 @@ justification = "JSON API") public abstract class GHHook extends GHObject { - /** The active. */ - boolean active; - - /** The config. */ - Map config; - - /** The events. */ - List events; - - /** The name. */ - String name; - /** * Create default GHHook instance */ public GHHook() { } - /** - * Deletes this hook. - * - * @throws IOException - * the io exception - */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); - } + /** The name. */ + String name; + + /** The events. */ + List events; + + /** The active. */ + boolean active; + + /** The config. */ + Map config; /** - * Gets config. + * Gets name. * - * @return the config + * @return the name */ - public Map getConfig() { - return Collections.unmodifiableMap(config); + public String getName() { + return name; } /** @@ -70,21 +60,21 @@ public EnumSet getEvents() { } /** - * Gets name. + * Is active boolean. * - * @return the name + * @return the boolean */ - public String getName() { - return name; + public boolean isActive() { + return active; } /** - * Is active boolean. + * Gets config. * - * @return the boolean + * @return the config */ - public boolean isActive() { - return active; + public Map getConfig() { + return Collections.unmodifiableMap(config); } /** @@ -99,11 +89,14 @@ public void ping() throws IOException { } /** - * Gets the api route. + * Deletes this hook. * - * @return the api route + * @throws IOException + * the io exception */ - abstract String getApiRoute(); + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + } /** * Root. @@ -111,4 +104,11 @@ public void ping() throws IOException { * @return the git hub */ abstract GitHub root(); + + /** + * Gets the api route. + * + * @return the api route + */ + abstract String getApiRoute(); } diff --git a/src/main/java/org/kohsuke/github/GHHooks.java b/src/main/java/org/kohsuke/github/GHHooks.java index 25fe143d82..addcad3179 100644 --- a/src/main/java/org/kohsuke/github/GHHooks.java +++ b/src/main/java/org/kohsuke/github/GHHooks.java @@ -14,66 +14,6 @@ */ class GHHooks { - private static class OrgContext extends Context { - private final GHOrganization organization; - - private OrgContext(GHOrganization organization) { - super(organization.root()); - this.organization = organization; - } - - @Override - Class clazz() { - return GHOrgHook.class; - } - - @Override - String collection() { - return String.format("/orgs/%s/hooks", organization.getLogin()); - } - - @Override - Class collectionClass() { - return GHOrgHook[].class; - } - - @Override - GHHook wrap(GHHook hook) { - return ((GHOrgHook) hook).wrap(organization); - } - } - - private static class RepoContext extends Context { - private final GHUser owner; - private final GHRepository repository; - - private RepoContext(GHRepository repository, GHUser owner) { - super(repository.root()); - this.repository = repository; - this.owner = owner; - } - - @Override - Class clazz() { - return GHRepoHook.class; - } - - @Override - String collection() { - return String.format("/repos/%s/%s/hooks", owner.getLogin(), repository.getName()); - } - - @Override - Class collectionClass() { - return GHRepoHook[].class; - } - - @Override - GHHook wrap(GHHook hook) { - return ((GHRepoHook) hook).wrap(repository); - } - } - /** * The Class Context. */ @@ -83,6 +23,39 @@ private Context(GitHub root) { super(root); } + /** + * Gets hooks. + * + * @return the hooks + * @throws IOException + * the io exception + */ + public List getHooks() throws IOException { + + // jdk/eclipse bug + GHHook[] hookArray = root().createRequest().withUrlPath(collection()).fetch(collectionClass()); + // requires this + // to be on separate line + List list = new ArrayList(Arrays.asList(hookArray)); + for (GHHook h : list) + wrap(h); + return list; + } + + /** + * Gets hook. + * + * @param id + * the id + * @return the hook + * @throws IOException + * the io exception + */ + public GHHook getHook(int id) throws IOException { + GHHook hook = root().createRequest().withUrlPath(collection() + "/" + id).fetch(clazz()); + return wrap(hook); + } + /** * Create hook gh hook. * @@ -132,37 +105,18 @@ public void deleteHook(int id) throws IOException { } /** - * Gets hook. + * Collection. * - * @param id - * the id - * @return the hook - * @throws IOException - * the io exception + * @return the string */ - public GHHook getHook(int id) throws IOException { - GHHook hook = root().createRequest().withUrlPath(collection() + "/" + id).fetch(clazz()); - return wrap(hook); - } + abstract String collection(); /** - * Gets hooks. + * Collection class. * - * @return the hooks - * @throws IOException - * the io exception + * @return the class */ - public List getHooks() throws IOException { - - // jdk/eclipse bug - GHHook[] hookArray = root().createRequest().withUrlPath(collection()).fetch(collectionClass()); - // requires this - // to be on separate line - List list = new ArrayList(Arrays.asList(hookArray)); - for (GHHook h : list) - wrap(h); - return list; - } + abstract Class collectionClass(); /** * Clazz. @@ -171,20 +125,6 @@ public List getHooks() throws IOException { */ abstract Class clazz(); - /** - * Collection. - * - * @return the string - */ - abstract String collection(); - - /** - * Collection class. - * - * @return the class - */ - abstract Class collectionClass(); - /** * Wrap. * @@ -195,15 +135,64 @@ public List getHooks() throws IOException { abstract GHHook wrap(GHHook hook); } - /** - * Org context. - * - * @param organization - * the organization - * @return the context - */ - static Context orgContext(GHOrganization organization) { - return new OrgContext(organization); + private static class RepoContext extends Context { + private final GHRepository repository; + private final GHUser owner; + + private RepoContext(GHRepository repository, GHUser owner) { + super(repository.root()); + this.repository = repository; + this.owner = owner; + } + + @Override + String collection() { + return String.format("/repos/%s/%s/hooks", owner.getLogin(), repository.getName()); + } + + @Override + Class collectionClass() { + return GHRepoHook[].class; + } + + @Override + Class clazz() { + return GHRepoHook.class; + } + + @Override + GHHook wrap(GHHook hook) { + return ((GHRepoHook) hook).wrap(repository); + } + } + + private static class OrgContext extends Context { + private final GHOrganization organization; + + private OrgContext(GHOrganization organization) { + super(organization.root()); + this.organization = organization; + } + + @Override + String collection() { + return String.format("/orgs/%s/hooks", organization.getLogin()); + } + + @Override + Class collectionClass() { + return GHOrgHook[].class; + } + + @Override + Class clazz() { + return GHOrgHook.class; + } + + @Override + GHHook wrap(GHHook hook) { + return ((GHOrgHook) hook).wrap(organization); + } } /** @@ -218,4 +207,15 @@ static Context orgContext(GHOrganization organization) { static Context repoContext(GHRepository repository, GHUser owner) { return new RepoContext(repository, owner); } + + /** + * Org context. + * + * @param organization + * the organization + * @return the context + */ + static Context orgContext(GHOrganization organization) { + return new OrgContext(organization); + } } diff --git a/src/main/java/org/kohsuke/github/GHInvitation.java b/src/main/java/org/kohsuke/github/GHInvitation.java index 726179d897..a625597b73 100644 --- a/src/main/java/org/kohsuke/github/GHInvitation.java +++ b/src/main/java/org/kohsuke/github/GHInvitation.java @@ -18,18 +18,18 @@ justification = "JSON API") public class GHInvitation extends GHObject { - private String htmlUrl; - - private int id; - private GHUser invitee, inviter; - private String permissions; - private GHRepository repository; /** * Create default GHInvitation instance */ public GHInvitation() { } + private int id; + private GHRepository repository; + private GHUser invitee, inviter; + private String permissions; + private String html_url; + /** * Accept a repository invitation. * @@ -56,6 +56,6 @@ public void decline() throws IOException { * @return the html url */ public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + return GitHubClient.parseURL(html_url); } } diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index e2d5e39bdb..15a7eb883f 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -24,14 +24,12 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import org.kohsuke.github.internal.EnumUtils; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -56,63 +54,15 @@ public class GHIssue extends GHObject implements Reactable { /** - * The type PullRequest. + * Create default GHIssue instance */ - @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") - public static class PullRequest { - - private String diffUrl, patchUrl, htmlUrl; - - /** - * Create default PullRequest instance - */ - public PullRequest() { - } - - /** - * Gets diff url. - * - * @return the diff url - */ - public URL getDiffUrl() { - return GitHubClient.parseURL(diffUrl); - } - - /** - * Gets patch url. - * - * @return the patch url - */ - public URL getPatchUrl() { - return GitHubClient.parseURL(patchUrl); - } - - /** - * Gets url. - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(htmlUrl); - } + public GHIssue() { } private static final String ASSIGNEES = "assignees"; - /** - * Gets the logins. - * - * @param users - * the users - * @return the logins - */ - protected static List getLogins(Collection users) { - List names = new ArrayList(users.size()); - for (GHUser a : users) { - names.add(a.getLogin()); - } - return names; - } + /** The owner. */ + GHRepository owner; /** The assignee. */ // API v3 @@ -121,163 +71,191 @@ protected static List getLogins(Collection users) { /** The assignees. */ protected GHUser[] assignees; - /** The body. */ - @SkipFromToString - protected String body; + /** The state. */ + protected String state; - /** The closed at. */ - protected String closedAt; + /** The state reason. */ + protected String state_reason; - /** The closed by. */ - protected GHUser closedBy; + /** The number. */ + protected int number; + + /** The closed at. */ + protected String closed_at; /** The comments. */ protected int comments; + /** The body. */ + @SkipFromToString + protected String body; + /** The labels. */ protected List labels; - /** The locked. */ - protected boolean locked; - - /** The milestone. */ - protected GHMilestone milestone; + /** The user. */ + protected GHUser user; - /** The number. */ - protected int number; + /** The html url. */ + protected String title, html_url; /** The pull request. */ - protected GHIssue.PullRequest pullRequest; + protected GHIssue.PullRequest pull_request; - /** The state. */ - protected String state; + /** The milestone. */ + protected GHMilestone milestone; - /** The state reason. */ - protected String stateReason; + /** The closed by. */ + protected GHUser closed_by; - /** The html url. */ - protected String title, htmlUrl; + /** The locked. */ + protected boolean locked; - /** The user. */ - protected GHUser user; + /** + * Wrap. + * + * @param owner + * the owner + * @return the GH issue + */ + GHIssue wrap(GHRepository owner) { + this.owner = owner; + if (milestone != null) + milestone.lateBind(owner); + return this; + } - /** The owner. */ - GHRepository owner; + private String getRepositoryUrlPath() { + String url = getUrl().toString(); + int index = url.indexOf("/issues"); + if (index == -1) { + index = url.indexOf("/pulls"); + } + return url.substring(0, index); + } /** - * Create default GHIssue instance + * Repository to which the issue belongs. + * + * @return the repository */ - public GHIssue() { + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getRepository() { + try { + synchronized (this) { + if (owner == null) { + String repositoryUrlPath = getRepositoryUrlPath(); + wrap(root().createRequest().withUrlPath(repositoryUrlPath).fetch(GHRepository.class)); + } + } + } catch (IOException e) { + throw new GHException("Failed to fetch repository", e); + } + return owner; } /** - * Add assignees. + * The description of this pull request. * - * @param assignees - * the assignees - * @throws IOException - * the io exception + * @return the body */ - public void addAssignees(Collection assignees) throws IOException { - root().createRequest() - .method("POST") - .with(ASSIGNEES, getLogins(assignees)) - .withUrlPath(getIssuesApiRoute() + "/assignees") - .fetchInto(this); + public String getBody() { + return body; } /** - * Add assignees. + * ID. * - * @param assignees - * the assignees - * @throws IOException - * the io exception + * @return the number */ - public void addAssignees(GHUser... assignees) throws IOException { - addAssignees(Arrays.asList(assignees)); + public int getNumber() { + return number; } /** - * Add labels. + * The HTML page of this issue, like https://github.com/jenkinsci/jenkins/issues/100 * - * Labels that are already present on the target are ignored. + * @return the html url + */ + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); + } + + /** + * Gets title. * - * @param labels - * the labels - * @return the complete list of labels including the new additions - * @throws IOException - * the io exception + * @return the title */ - public List addLabels(Collection labels) throws IOException { - return _addLabels(GHLabel.toNames(labels)); + public String getTitle() { + return title; } /** - * Add labels. + * Is locked boolean. * - * Labels that are already present on the target are ignored. + * @return the boolean + */ + public boolean isLocked() { + return locked; + } + + /** + * Gets state. * - * @param labels - * the labels - * @return the complete list of labels including the new additions - * @throws IOException - * the io exception + * @return the state */ - public List addLabels(GHLabel... labels) throws IOException { - return addLabels(Arrays.asList(labels)); + public GHIssueState getState() { + return Enum.valueOf(GHIssueState.class, state.toUpperCase(Locale.ENGLISH)); } /** - * Adds labels to the issue. + * Gets state reason. * - * Labels that are already present on the target are ignored. + * @return the state reason + */ + public GHIssueStateReason getStateReason() { + return EnumUtils.getNullableEnumOrDefault(GHIssueStateReason.class, state_reason, GHIssueStateReason.UNKNOWN); + } + + /** + * Gets labels. * - * @param names - * Names of the label - * @return the complete list of labels including the new additions - * @throws IOException - * the io exception + * @return the labels */ - public List addLabels(String... names) throws IOException { - return _addLabels(Arrays.asList(names)); + public Collection getLabels() { + if (labels == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(labels); } /** - * Assign to. + * Gets closed at. * - * @param user - * the user - * @throws IOException - * the io exception + * @return the closed at */ - public void assignTo(GHUser user) throws IOException { - setAssignees(user); + public Date getClosedAt() { + return GitHubClient.parseDate(closed_at); } /** - * Closes this issue. + * Lock. * * @throws IOException * the io exception */ - public void close() throws IOException { - edit("state", "closed"); + public void lock() throws IOException { + root().createRequest().method("PUT").withUrlPath(getApiRoute() + "/lock").send(); } /** - * Closes this issue. + * Unlock. * - * @param reason - * the reason the issue was closed * @throws IOException * the io exception */ - public void close(GHIssueStateReason reason) throws IOException { - Map map = new HashMap<>(); - map.put("state", "closed"); - map.put("state_reason", reason.name().toLowerCase(Locale.ENGLISH)); - edit(map); + public void unlock() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute() + "/lock").send(); } /** @@ -298,285 +276,280 @@ public GHIssueComment comment(String message) throws IOException { return r.wrapUp(this); } + private void edit(String key, Object value) throws IOException { + root().createRequest().with(key, value).method("PATCH").withUrlPath(getApiRoute()).send(); + } + + private void edit(Map map) throws IOException { + root().createRequest().with(map).method("PATCH").withUrlPath(getApiRoute()).send(); + } + /** - * Creates the reaction. - * - * @param content - * the content - * @return the GH reaction - * @throws IOException - * Signals that an I/O exception has occurred. + * Identical to edit(), but allows null for the value. */ - public GHReaction createReaction(ReactionContent content) throws IOException { - return root().createRequest() - .method("POST") - .with("content", content.getContent()) - .withUrlPath(getIssuesApiRoute() + "/reactions") - .fetch(GHReaction.class); + private void editNullable(String key, Object value) throws IOException { + root().createRequest().withNullable(key, value).method("PATCH").withUrlPath(getApiRoute()).send(); + } + + private void editIssue(String key, Object value) throws IOException { + root().createRequest().withNullable(key, value).method("PATCH").withUrlPath(getIssuesApiRoute()).send(); } /** - * Delete reaction. + * Closes this issue. * - * @param reaction - * the reaction * @throws IOException - * Signals that an I/O exception has occurred. + * the io exception */ - public void deleteReaction(GHReaction reaction) throws IOException { - owner.root() - .createRequest() - .method("DELETE") - .withUrlPath(getIssuesApiRoute(), "reactions", String.valueOf(reaction.getId())) - .send(); + public void close() throws IOException { + edit("state", "closed"); } /** - * Gets assignee. + * Closes this issue. * - * @return the assignee + * @param reason + * the reason the issue was closed + * @throws IOException + * the io exception */ - public GHUser getAssignee() { - return root().intern(assignee); + public void close(GHIssueStateReason reason) throws IOException { + Map map = new HashMap<>(); + map.put("state", "closed"); + map.put("state_reason", reason.name().toLowerCase(Locale.ENGLISH)); + edit(map); } /** - * Gets assignees. + * Reopens this issue. * - * @return the assignees + * @throws IOException + * the io exception */ - public List getAssignees() { - return Collections.unmodifiableList(Arrays.asList(assignees)); + public void reopen() throws IOException { + edit("state", "open"); } /** - * The description of this pull request. + * Sets title. * - * @return the body + * @param title + * the title + * @throws IOException + * the io exception */ - public String getBody() { - return body; + public void setTitle(String title) throws IOException { + edit("title", title); } /** - * Gets closed at. + * Sets body. * - * @return the closed at + * @param body + * the body + * @throws IOException + * the io exception */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getClosedAt() { - return GitHubClient.parseInstant(closedAt); + public void setBody(String body) throws IOException { + edit("body", body); } /** - * Reports who has closed the issue. - * - *

- * Note that GitHub doesn't always seem to report this information even for an issue that's already closed. See - * https://github.com/kohsuke/github-api/issues/60. + * Sets the milestone for this issue. * - * @return the closed by + * @param milestone + * The milestone to assign this issue to. Use null to remove the milestone for this issue. + * @throws IOException + * The io exception */ - public GHUser getClosedBy() { - if (!"closed".equals(state)) - return null; - - // TODO - /* - * if (closed_by==null) { closed_by = owner.getIssue(number).getClosed_by(); } - */ - return root().intern(closedBy); + public void setMilestone(GHMilestone milestone) throws IOException { + if (milestone == null) { + editIssue("milestone", null); + } else { + editIssue("milestone", milestone.getNumber()); + } } /** - * Obtains all the comments associated with this issue. + * Assign to. * - * @return the comments + * @param user + * the user * @throws IOException * the io exception - * @see #listComments() #listComments() */ - public List getComments() throws IOException { - return listComments().toList(); + public void assignTo(GHUser user) throws IOException { + setAssignees(user); } /** - * Gets comments count. + * Sets labels on the target to a specific list. * - * @return the comments count + * @param labels + * the labels + * @throws IOException + * the io exception */ - public int getCommentsCount() { - return comments; + public void setLabels(String... labels) throws IOException { + editIssue("labels", labels); } /** - * The HTML page of this issue, like https://github.com/jenkinsci/jenkins/issues/100 + * Adds labels to the issue. * - * @return the html url - */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); - } - - /** - * Gets labels. + * Labels that are already present on the target are ignored. * - * @return the labels + * @param names + * Names of the label + * @return the complete list of labels including the new additions + * @throws IOException + * the io exception */ - public Collection getLabels() { - if (labels == null) { - return Collections.emptyList(); - } - return Collections.unmodifiableList(labels); + public List addLabels(String... names) throws IOException { + return _addLabels(Arrays.asList(names)); } /** - * Gets milestone. + * Add labels. * - * @return the milestone - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHMilestone getMilestone() { - return milestone; - } - - /** - * ID. + * Labels that are already present on the target are ignored. * - * @return the number + * @param labels + * the labels + * @return the complete list of labels including the new additions + * @throws IOException + * the io exception */ - public int getNumber() { - return number; + public List addLabels(GHLabel... labels) throws IOException { + return addLabels(Arrays.asList(labels)); } /** - * Returns non-null if this issue is a shadow of a pull request. + * Add labels. * - * @return the pull request + * Labels that are already present on the target are ignored. + * + * @param labels + * the labels + * @return the complete list of labels including the new additions + * @throws IOException + * the io exception */ - public PullRequest getPullRequest() { - return pullRequest; + public List addLabels(Collection labels) throws IOException { + return _addLabels(GHLabel.toNames(labels)); } - /** - * Repository to which the issue belongs. - * - * @return the repository - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getRepository() { - try { - synchronized (this) { - if (owner == null) { - String repositoryUrlPath = getRepositoryUrlPath(); - wrap(root().createRequest().withUrlPath(repositoryUrlPath).fetch(GHRepository.class)); - } - } - } catch (IOException e) { - throw new GHException("Failed to fetch repository", e); - } - return owner; + private List _addLabels(Collection names) throws IOException { + return Arrays.asList(root().createRequest() + .with("labels", names) + .method("POST") + .withUrlPath(getIssuesApiRoute() + "/labels") + .fetch(GHLabel[].class)); } /** - * Gets state. + * Remove a single label. * - * @return the state + * Attempting to remove a label that is not present throws {@link GHFileNotFoundException}. + * + * @param name + * the name + * @return the remaining list of labels + * @throws IOException + * the io exception, throws {@link GHFileNotFoundException} if label was not present. */ - public GHIssueState getState() { - return Enum.valueOf(GHIssueState.class, state.toUpperCase(Locale.ENGLISH)); + public List removeLabel(String name) throws IOException { + return Arrays.asList(root().createRequest() + .method("DELETE") + .withUrlPath(getIssuesApiRoute() + "/labels", name) + .fetch(GHLabel[].class)); } /** - * Gets state reason. + * Remove a collection of labels. * - * @return the state reason + * Attempting to remove labels that are not present on the target are ignored. + * + * @param names + * the names + * @return the remaining list of labels + * @throws IOException + * the io exception */ - public GHIssueStateReason getStateReason() { - return EnumUtils.getNullableEnumOrDefault(GHIssueStateReason.class, stateReason, GHIssueStateReason.UNKNOWN); + public List removeLabels(String... names) throws IOException { + return _removeLabels(Arrays.asList(names)); } /** - * Gets title. + * Remove a collection of labels. * - * @return the title + * Attempting to remove labels that are not present on the target are ignored. + * + * @param labels + * the labels + * @return the remaining list of labels + * @throws IOException + * the io exception + * @see #removeLabels(String...) #removeLabels(String...) */ - public String getTitle() { - return title; + public List removeLabels(GHLabel... labels) throws IOException { + return removeLabels(Arrays.asList(labels)); } /** - * User who submitted the issue. + * Remove a collection of labels. * - * @return the user + * Attempting to remove labels that are not present on the target are ignored. + * + * @param labels + * the labels + * @return the remaining list of labels + * @throws IOException + * the io exception */ - public GHUser getUser() { - return root().intern(user); + public List removeLabels(Collection labels) throws IOException { + return _removeLabels(GHLabel.toNames(labels)); } - /** - * Is locked boolean. - * - * @return the boolean - */ - public boolean isLocked() { - return locked; + private List _removeLabels(Collection names) throws IOException { + List remainingLabels = Collections.emptyList(); + for (String name : names) { + try { + remainingLabels = removeLabel(name); + } catch (GHFileNotFoundException e) { + // when trying to remove multiple labels, we ignore already removed + } + } + return remainingLabels; } /** - * Is pull request boolean. + * Obtains all the comments associated with this issue. * - * @return the boolean + * @return the comments + * @throws IOException + * the io exception + * @see #listComments() #listComments() */ - public boolean isPullRequest() { - return pullRequest != null; + public List getComments() throws IOException { + return listComments().toList(); } /** * Obtains all the comments associated with this issue, without any filter. * * @return the paged iterable + * @throws IOException + * the io exception * @see List issue comments * @see #queryComments() queryComments to apply filters. */ - public PagedIterable listComments() { + public PagedIterable listComments() throws IOException { return root().createRequest() .withUrlPath(getIssuesApiRoute() + "/comments") .toIterable(GHIssueComment[].class, item -> item.wrapUp(this)); } - /** - * Lists events for this issue. See https://developer.github.com/v3/issues/events/ - * - * @return the paged iterable - */ - public PagedIterable listEvents() { - return root().createRequest() - .withUrlPath(getRepository().getApiTailUrl(String.format("/issues/%s/events", number))) - .toIterable(GHIssueEvent[].class, item -> item.wrapUp(this)); - } - - /** - * List reactions. - * - * @return the paged iterable - */ - public PagedIterable listReactions() { - return root().createRequest() - .withUrlPath(getIssuesApiRoute() + "/reactions") - .toIterable(GHReaction[].class, null); - } - - /** - * Lock. - * - * @throws IOException - * the io exception - */ - public void lock() throws IOException { - root().createRequest().method("PUT").withUrlPath(getApiRoute() + "/lock").send(); - } - /** * Search comments on this issue by specifying filters through a builder pattern. * @@ -588,106 +561,87 @@ public GHIssueCommentQueryBuilder queryComments() { } /** - * Remove assignees. - * - * @param assignees - * the assignees - * @throws IOException - * the io exception - */ - public void removeAssignees(Collection assignees) throws IOException { - root().createRequest() - .method("DELETE") - .with(ASSIGNEES, getLogins(assignees)) - .inBody() - .withUrlPath(getIssuesApiRoute() + "/assignees") - .fetchInto(this); - } - - /** - * Remove assignees. + * Creates the reaction. * - * @param assignees - * the assignees + * @param content + * the content + * @return the GH reaction * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public void removeAssignees(GHUser... assignees) throws IOException { - removeAssignees(Arrays.asList(assignees)); + public GHReaction createReaction(ReactionContent content) throws IOException { + return root().createRequest() + .method("POST") + .with("content", content.getContent()) + .withUrlPath(getIssuesApiRoute() + "/reactions") + .fetch(GHReaction.class); } /** - * Remove a single label. - * - * Attempting to remove a label that is not present throws {@link GHFileNotFoundException}. + * Delete reaction. * - * @param name - * the name - * @return the remaining list of labels + * @param reaction + * the reaction * @throws IOException - * the io exception, throws {@link GHFileNotFoundException} if label was not present. + * Signals that an I/O exception has occurred. */ - public List removeLabel(String name) throws IOException { - return Arrays.asList(root().createRequest() + public void deleteReaction(GHReaction reaction) throws IOException { + owner.root() + .createRequest() .method("DELETE") - .withUrlPath(getIssuesApiRoute() + "/labels", name) - .fetch(GHLabel[].class)); + .withUrlPath(getIssuesApiRoute(), "reactions", String.valueOf(reaction.getId())) + .send(); } /** - * Remove a collection of labels. - * - * Attempting to remove labels that are not present on the target are ignored. + * List reactions. * - * @param labels - * the labels - * @return the remaining list of labels - * @throws IOException - * the io exception + * @return the paged iterable */ - public List removeLabels(Collection labels) throws IOException { - return _removeLabels(GHLabel.toNames(labels)); + public PagedIterable listReactions() { + return root().createRequest() + .withUrlPath(getIssuesApiRoute() + "/reactions") + .toIterable(GHReaction[].class, null); } /** - * Remove a collection of labels. - * - * Attempting to remove labels that are not present on the target are ignored. + * Add assignees. * - * @param labels - * the labels - * @return the remaining list of labels + * @param assignees + * the assignees * @throws IOException * the io exception - * @see #removeLabels(String...) #removeLabels(String...) */ - public List removeLabels(GHLabel... labels) throws IOException { - return removeLabels(Arrays.asList(labels)); + public void addAssignees(GHUser... assignees) throws IOException { + addAssignees(Arrays.asList(assignees)); } /** - * Remove a collection of labels. - * - * Attempting to remove labels that are not present on the target are ignored. + * Add assignees. * - * @param names - * the names - * @return the remaining list of labels + * @param assignees + * the assignees * @throws IOException * the io exception */ - public List removeLabels(String... names) throws IOException { - return _removeLabels(Arrays.asList(names)); + public void addAssignees(Collection assignees) throws IOException { + root().createRequest() + .method("POST") + .with(ASSIGNEES, getLogins(assignees)) + .withUrlPath(getIssuesApiRoute() + "/assignees") + .fetchInto(this); } /** - * Reopens this issue. + * Sets assignees. * + * @param assignees + * the assignees * @throws IOException * the io exception */ - public void reopen() throws IOException { - edit("state", "open"); + public void setAssignees(GHUser... assignees) throws IOException { + setAssignees(Arrays.asList(assignees)); } /** @@ -707,162 +661,215 @@ public void setAssignees(Collection assignees) throws IOException { } /** - * Sets assignees. + * Remove assignees. * * @param assignees * the assignees * @throws IOException * the io exception */ - public void setAssignees(GHUser... assignees) throws IOException { - setAssignees(Arrays.asList(assignees)); + public void removeAssignees(GHUser... assignees) throws IOException { + removeAssignees(Arrays.asList(assignees)); } /** - * Sets body. + * Remove assignees. * - * @param body - * the body + * @param assignees + * the assignees * @throws IOException * the io exception */ - public void setBody(String body) throws IOException { - edit("body", body); + public void removeAssignees(Collection assignees) throws IOException { + root().createRequest() + .method("DELETE") + .with(ASSIGNEES, getLogins(assignees)) + .inBody() + .withUrlPath(getIssuesApiRoute() + "/assignees") + .fetchInto(this); } /** - * Sets labels on the target to a specific list. + * Gets api route. * - * @param labels - * the labels - * @throws IOException - * the io exception + * @return the api route */ - public void setLabels(String... labels) throws IOException { - editIssue("labels", labels); + protected String getApiRoute() { + return getIssuesApiRoute(); } /** - * Sets the milestone for this issue. + * Gets issues api route. * - * @param milestone - * The milestone to assign this issue to. Use null to remove the milestone for this issue. - * @throws IOException - * The io exception + * @return the issues api route */ - public void setMilestone(GHMilestone milestone) throws IOException { - if (milestone == null) { - editIssue("milestone", null); - } else { - editIssue("milestone", milestone.getNumber()); + protected String getIssuesApiRoute() { + if (owner == null) { + // Issues returned from search to do not have an owner. Attempt to use url. + final URL url = Objects.requireNonNull(getUrl(), "Missing instance URL!"); + return StringUtils.prependIfMissing(url.toString().replace(root().getApiUrl(), ""), "/"); } + GHRepository repo = getRepository(); + return "/repos/" + repo.getOwnerName() + "/" + repo.getName() + "/issues/" + number; } /** - * Sets title. + * Gets assignee. * - * @param title - * the title + * @return the assignee * @throws IOException * the io exception */ - public void setTitle(String title) throws IOException { - edit("title", title); + public GHUser getAssignee() throws IOException { + return root().intern(assignee); } /** - * Unlock. + * Gets assignees. * - * @throws IOException - * the io exception + * @return the assignees */ - public void unlock() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute() + "/lock").send(); + public List getAssignees() { + return Collections.unmodifiableList(Arrays.asList(assignees)); } - private List _addLabels(Collection names) throws IOException { - return Arrays.asList(root().createRequest() - .with("labels", names) - .method("POST") - .withUrlPath(getIssuesApiRoute() + "/labels") - .fetch(GHLabel[].class)); + /** + * User who submitted the issue. + * + * @return the user + * @throws IOException + * the io exception + */ + public GHUser getUser() throws IOException { + return root().intern(user); } - private List _removeLabels(Collection names) throws IOException { - List remainingLabels = Collections.emptyList(); - for (String name : names) { - try { - remainingLabels = removeLabel(name); - } catch (GHFileNotFoundException e) { - // when trying to remove multiple labels, we ignore already removed - } - } - return remainingLabels; - } + /** + * Reports who has closed the issue. + * + *

+ * Note that GitHub doesn't always seem to report this information even for an issue that's already closed. See + * https://github.com/kohsuke/github-api/issues/60. + * + * @return the closed by + * @throws IOException + * the io exception + */ + public GHUser getClosedBy() throws IOException { + if (!"closed".equals(state)) + return null; - private void edit(Map map) throws IOException { - root().createRequest().with(map).method("PATCH").withUrlPath(getApiRoute()).send(); + // TODO + /* + * if (closed_by==null) { closed_by = owner.getIssue(number).getClosed_by(); } + */ + return root().intern(closed_by); } - private void edit(String key, Object value) throws IOException { - root().createRequest().with(key, value).method("PATCH").withUrlPath(getApiRoute()).send(); + /** + * Gets comments count. + * + * @return the comments count + */ + public int getCommentsCount() { + return comments; } - private void editIssue(String key, Object value) throws IOException { - root().createRequest().withNullable(key, value).method("PATCH").withUrlPath(getIssuesApiRoute()).send(); + /** + * Returns non-null if this issue is a shadow of a pull request. + * + * @return the pull request + */ + public PullRequest getPullRequest() { + return pull_request; } /** - * Identical to edit(), but allows null for the value. + * Is pull request boolean. + * + * @return the boolean */ - private void editNullable(String key, Object value) throws IOException { - root().createRequest().withNullable(key, value).method("PATCH").withUrlPath(getApiRoute()).send(); + public boolean isPullRequest() { + return pull_request != null; } - private String getRepositoryUrlPath() { - String url = getUrl().toString(); - int index = url.indexOf("/issues"); - if (index == -1) { - index = url.indexOf("/pulls"); - } - return url.substring(0, index); + /** + * Gets milestone. + * + * @return the milestone + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHMilestone getMilestone() { + return milestone; } /** - * Gets api route. - * - * @return the api route + * The type PullRequest. */ - protected String getApiRoute() { - return getIssuesApiRoute(); + @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") + public static class PullRequest { + + /** + * Create default PullRequest instance + */ + public PullRequest() { + } + + private String diff_url, patch_url, html_url; + + /** + * Gets diff url. + * + * @return the diff url + */ + public URL getDiffUrl() { + return GitHubClient.parseURL(diff_url); + } + + /** + * Gets patch url. + * + * @return the patch url + */ + public URL getPatchUrl() { + return GitHubClient.parseURL(patch_url); + } + + /** + * Gets url. + * + * @return the url + */ + public URL getUrl() { + return GitHubClient.parseURL(html_url); + } } /** - * Gets issues api route. + * Gets the logins. * - * @return the issues api route + * @param users + * the users + * @return the logins */ - protected String getIssuesApiRoute() { - if (owner == null) { - // Issues returned from search to do not have an owner. Attempt to use url. - final URL url = Objects.requireNonNull(getUrl(), "Missing instance URL!"); - return StringUtils.prependIfMissing(url.toString().replace(root().getApiUrl(), ""), "/"); + protected static List getLogins(Collection users) { + List names = new ArrayList(users.size()); + for (GHUser a : users) { + names.add(a.getLogin()); } - GHRepository repo = getRepository(); - return "/repos/" + repo.getOwnerName() + "/" + repo.getName() + "/issues/" + number; + return names; } /** - * Wrap. + * Lists events for this issue. See https://developer.github.com/v3/issues/events/ * - * @param owner - * the owner - * @return the GH issue + * @return the paged iterable + * @throws IOException + * the io exception */ - GHIssue wrap(GHRepository owner) { - this.owner = owner; - if (milestone != null) - milestone.lateBind(owner); - return this; + public PagedIterable listEvents() throws IOException { + return root().createRequest() + .withUrlPath(getRepository().getApiTailUrl(String.format("/issues/%s/events", number))) + .toIterable(GHIssueEvent[].class, item -> item.wrapUp(this)); } } diff --git a/src/main/java/org/kohsuke/github/GHIssueBuilder.java b/src/main/java/org/kohsuke/github/GHIssueBuilder.java index 451891f99a..0d904c4fb2 100644 --- a/src/main/java/org/kohsuke/github/GHIssueBuilder.java +++ b/src/main/java/org/kohsuke/github/GHIssueBuilder.java @@ -11,10 +11,10 @@ * @author Kohsuke Kawaguchi */ public class GHIssueBuilder { - private List assignees = new ArrayList(); + private final GHRepository repo; private final Requester builder; private List labels = new ArrayList(); - private final GHRepository repo; + private List assignees = new ArrayList(); /** * Instantiates a new GH issue builder. @@ -30,6 +30,18 @@ public class GHIssueBuilder { builder.with("title", title); } + /** + * Sets the main text of an issue, which is arbitrary multi-line text. + * + * @param str + * the str + * @return the gh issue builder + */ + public GHIssueBuilder body(String str) { + builder.with("body", str); + return this; + } + /** * Assignee gh issue builder. * @@ -57,32 +69,18 @@ public GHIssueBuilder assignee(String user) { } /** - * Sets the main text of an issue, which is arbitrary multi-line text. + * Milestone gh issue builder. * - * @param str - * the str + * @param milestone + * the milestone * @return the gh issue builder */ - public GHIssueBuilder body(String str) { - builder.with("body", str); + public GHIssueBuilder milestone(GHMilestone milestone) { + if (milestone != null) + builder.with("milestone", milestone.getNumber()); return this; } - /** - * Creates a new issue. - * - * @return the gh issue - * @throws IOException - * the io exception - */ - public GHIssue create() throws IOException { - return builder.with("labels", labels) - .with("assignees", assignees) - .withUrlPath(repo.getApiTailUrl("issues")) - .fetch(GHIssue.class) - .wrap(repo); - } - /** * Label gh issue builder. * @@ -97,15 +95,17 @@ public GHIssueBuilder label(String label) { } /** - * Milestone gh issue builder. + * Creates a new issue. * - * @param milestone - * the milestone - * @return the gh issue builder + * @return the gh issue + * @throws IOException + * the io exception */ - public GHIssueBuilder milestone(GHMilestone milestone) { - if (milestone != null) - builder.with("milestone", milestone.getNumber()); - return this; + public GHIssue create() throws IOException { + return builder.with("labels", labels) + .with("assignees", assignees) + .withUrlPath(repo.getApiTailUrl("issues")) + .fetch(GHIssue.class) + .wrap(repo); } } diff --git a/src/main/java/org/kohsuke/github/GHIssueChanges.java b/src/main/java/org/kohsuke/github/GHIssueChanges.java index 200ff93ee8..d47b8cdcc0 100644 --- a/src/main/java/org/kohsuke/github/GHIssueChanges.java +++ b/src/main/java/org/kohsuke/github/GHIssueChanges.java @@ -12,35 +12,21 @@ public class GHIssueChanges { /** - * Wrapper for changed values. + * Create default GHIssueChanges instance */ - public static class GHFrom { - - private String from; - - /** - * Create default GHFrom instance - */ - public GHFrom() { - } - - /** - * Previous value that was changed. - * - * @return previous value - */ - public String getFrom() { - return from; - } + public GHIssueChanges() { } - private GHFrom body; private GHFrom title; + private GHFrom body; /** - * Create default GHIssueChanges instance + * Old issue title. + * + * @return old issue title (or null if not changed) */ - public GHIssueChanges() { + public GHFrom getTitle() { + return title; } /** @@ -53,11 +39,25 @@ public GHFrom getBody() { } /** - * Old issue title. - * - * @return old issue title (or null if not changed) + * Wrapper for changed values. */ - public GHFrom getTitle() { - return title; + public static class GHFrom { + + /** + * Create default GHFrom instance + */ + public GHFrom() { + } + + private String from; + + /** + * Previous value that was changed. + * + * @return previous value + */ + public String getFrom() { + return from; + } } } diff --git a/src/main/java/org/kohsuke/github/GHIssueComment.java b/src/main/java/org/kohsuke/github/GHIssueComment.java index 51415248d6..2c6d8f9561 100644 --- a/src/main/java/org/kohsuke/github/GHIssueComment.java +++ b/src/main/java/org/kohsuke/github/GHIssueComment.java @@ -24,7 +24,6 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import org.kohsuke.github.internal.EnumUtils; import java.io.IOException; import java.net.URL; @@ -39,60 +38,67 @@ */ public class GHIssueComment extends GHObject implements Reactable { - private String body, gravatarId, htmlUrl, authorAssociation; - - private GHUser user; // not fully populated. beware. + /** + * Create default GHIssueComment instance + */ + public GHIssueComment() { + } /** The owner. */ GHIssue owner; + + private String body, gravatar_id, html_url, author_association; + private GHUser user; // not fully populated. beware. + /** - * Create default GHIssueComment instance + * Wrap up. + * + * @param owner + * the owner + * @return the GH issue comment */ - public GHIssueComment() { + GHIssueComment wrapUp(GHIssue owner) { + this.owner = owner; + return this; } /** - * Creates the reaction. + * Gets the issue to which this comment is associated. * - * @param content - * the content - * @return the GH reaction - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the parent */ - public GHReaction createReaction(ReactionContent content) throws IOException { - return owner.root() - .createRequest() - .method("POST") - .with("content", content.getContent()) - .withUrlPath(getApiRoute() + "/reactions") - .fetch(GHReaction.class); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHIssue getParent() { + return owner; } /** - * Deletes this issue comment. + * The comment itself. + * + * @return the body + */ + public String getBody() { + return body; + } + + /** + * Gets the user who posted this comment. * + * @return the user * @throws IOException * the io exception */ - public void delete() throws IOException { - owner.root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + public GHUser getUser() throws IOException { + return owner == null || owner.isOffline() ? user : owner.root().getUser(user.getLogin()); } /** - * Delete reaction. + * Gets the html url. * - * @param reaction - * the reaction - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the html url */ - public void deleteReaction(GHReaction reaction) throws IOException { - owner.root() - .createRequest() - .method("DELETE") - .withUrlPath(getApiRoute(), "reactions", String.valueOf(reaction.getId())) - .send(); + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); } /** @@ -101,48 +107,69 @@ public void deleteReaction(GHReaction reaction) throws IOException { * @return the author association */ public GHCommentAuthorAssociation getAuthorAssociation() { - return EnumUtils.getEnumOrDefault(GHCommentAuthorAssociation.class, - authorAssociation, - GHCommentAuthorAssociation.UNKNOWN); + return GHCommentAuthorAssociation.valueOf(author_association); } /** - * The comment itself. + * Updates the body of the issue comment. * - * @return the body + * @param body + * the body + * @throws IOException + * the io exception */ - public String getBody() { - return body; + public void update(String body) throws IOException { + owner.root() + .createRequest() + .method("PATCH") + .with("body", body) + .withUrlPath(getApiRoute()) + .fetch(GHIssueComment.class); + this.body = body; } /** - * Gets the html url. + * Deletes this issue comment. * - * @return the html url + * @throws IOException + * the io exception */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public void delete() throws IOException { + owner.root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } /** - * Gets the issue to which this comment is associated. + * Creates the reaction. * - * @return the parent + * @param content + * the content + * @return the GH reaction + * @throws IOException + * Signals that an I/O exception has occurred. */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHIssue getParent() { - return owner; + public GHReaction createReaction(ReactionContent content) throws IOException { + return owner.root() + .createRequest() + .method("POST") + .with("content", content.getContent()) + .withUrlPath(getApiRoute() + "/reactions") + .fetch(GHReaction.class); } /** - * Gets the user who posted this comment. + * Delete reaction. * - * @return the user + * @param reaction + * the reaction * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public GHUser getUser() throws IOException { - return owner == null || owner.isOffline() ? user : owner.root().getUser(user.getLogin()); + public void deleteReaction(GHReaction reaction) throws IOException { + owner.root() + .createRequest() + .method("DELETE") + .withUrlPath(getApiRoute(), "reactions", String.valueOf(reaction.getId())) + .send(); } /** @@ -157,38 +184,8 @@ public PagedIterable listReactions() { .toIterable(GHReaction[].class, item -> owner.root()); } - /** - * Updates the body of the issue comment. - * - * @param body - * the body - * @throws IOException - * the io exception - */ - public void update(String body) throws IOException { - owner.root() - .createRequest() - .method("PATCH") - .with("body", body) - .withUrlPath(getApiRoute()) - .fetch(GHIssueComment.class); - this.body = body; - } - private String getApiRoute() { return "/repos/" + owner.getRepository().getOwnerName() + "/" + owner.getRepository().getName() + "/issues/comments/" + getId(); } - - /** - * Wrap up. - * - * @param owner - * the owner - * @return the GH issue comment - */ - GHIssueComment wrapUp(GHIssue owner) { - this.owner = owner; - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHIssueCommentQueryBuilder.java b/src/main/java/org/kohsuke/github/GHIssueCommentQueryBuilder.java index 920644d20b..d39df0d475 100644 --- a/src/main/java/org/kohsuke/github/GHIssueCommentQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHIssueCommentQueryBuilder.java @@ -1,6 +1,5 @@ package org.kohsuke.github; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -21,8 +20,8 @@ * @see List issue comments */ public class GHIssueCommentQueryBuilder { - private final GHIssue issue; private final Requester req; + private final GHIssue issue; /** * Instantiates a new GH issue comment query builder. @@ -35,37 +34,15 @@ public class GHIssueCommentQueryBuilder { this.req = issue.root().createRequest().withUrlPath(issue.getIssuesApiRoute() + "/comments"); } - /** - * Lists up the comments with the criteria added so far. - * - * @return the paged iterable - */ - public PagedIterable list() { - return req.toIterable(GHIssueComment[].class, item -> item.wrapUp(issue)); - } - /** * Only comments created/updated after this date will be returned. * * @param date * the date * @return the query builder - * @deprecated Use {@link #since(Instant)} */ - @Deprecated public GHIssueCommentQueryBuilder since(Date date) { - return since(GitHubClient.toInstantOrNull(date)); - } - - /** - * Only comments created/updated after this date will be returned. - * - * @param date - * the date - * @return the query builder - */ - public GHIssueCommentQueryBuilder since(Instant date) { - req.with("since", GitHubClient.printInstant(date)); + req.with("since", GitHubClient.printDate(date)); return this; } @@ -77,6 +54,15 @@ public GHIssueCommentQueryBuilder since(Instant date) { * @return the query builder */ public GHIssueCommentQueryBuilder since(long timestamp) { - return since(Instant.ofEpochMilli(timestamp)); + return since(new Date(timestamp)); + } + + /** + * Lists up the comments with the criteria added so far. + * + * @return the paged iterable + */ + public PagedIterable list() { + return req.toIterable(GHIssueComment[].class, item -> item.wrapUp(issue)); } } diff --git a/src/main/java/org/kohsuke/github/GHIssueEvent.java b/src/main/java/org/kohsuke/github/GHIssueEvent.java index aff93f135e..726a590989 100644 --- a/src/main/java/org/kohsuke/github/GHIssueEvent.java +++ b/src/main/java/org/kohsuke/github/GHIssueEvent.java @@ -1,9 +1,7 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -15,27 +13,54 @@ */ public class GHIssueEvent extends GitHubInteractiveObject { - private GHUser actor; + /** + * Create default GHIssueEvent instance + */ + public GHIssueEvent() { + } - private GHUser assignee; - private String commitId; - private String commitUrl; - private String createdAt; - private String event; private long id; - private GHIssue issue; - private GHLabel label; + private String node_id; + private String url; + private GHUser actor; + private String event; + private String commit_id; + private String commit_url; + private String created_at; private GHMilestone milestone; - private String nodeId; + private GHLabel label; + private GHUser assignee; private GHIssueRename rename; - private GHUser requestedReviewer; private GHUser reviewRequester; - private String url; + private GHUser requestedReviewer; + + private GHIssue issue; /** - * Create default GHIssueEvent instance + * Gets id. + * + * @return the id */ - public GHIssueEvent() { + public long getId() { + return id; + } + + /** + * Gets node id. + * + * @return the node id + */ + public String getNodeId() { + return node_id; + } + + /** + * Gets url. + * + * @return the url + */ + public String getUrl() { + return url; } /** @@ -49,14 +74,12 @@ public GHUser getActor() { } /** - * Get the {@link GHUser} that was assigned or unassigned from the issue. Only present for events "assigned" and - * "unassigned", null otherwise. + * Gets event. * - * @return the user + * @return the event */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getAssignee() { - return assignee; + public String getEvent() { + return event; } /** @@ -65,7 +88,7 @@ public GHUser getAssignee() { * @return the commit id */ public String getCommitId() { - return commitId; + return commit_id; } /** @@ -74,7 +97,7 @@ public String getCommitId() { * @return the commit url */ public String getCommitUrl() { - return commitUrl; + return commit_url; } /** @@ -82,37 +105,29 @@ public String getCommitUrl() { * * @return the created at */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCreatedAt() { - return GitHubClient.parseInstant(createdAt); - } - - /** - * Gets event. - * - * @return the event - */ - public String getEvent() { - return event; + public Date getCreatedAt() { + return GitHubClient.parseDate(created_at); } /** - * Gets id. + * Gets issue. * - * @return the id + * @return the issue */ - public long getId() { - return id; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHIssue getIssue() { + return issue; } /** - * Gets issue. + * Get the {@link GHMilestone} that this issue was added to or removed from. Only present for events "milestoned" + * and "demilestoned", null otherwise. * - * @return the issue + * @return the milestone */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHIssue getIssue() { - return issue; + public GHMilestone getMilestone() { + return milestone; } /** @@ -127,23 +142,14 @@ public GHLabel getLabel() { } /** - * Get the {@link GHMilestone} that this issue was added to or removed from. Only present for events "milestoned" - * and "demilestoned", null otherwise. + * Get the {@link GHUser} that was assigned or unassigned from the issue. Only present for events "assigned" and + * "unassigned", null otherwise. * - * @return the milestone + * @return the user */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHMilestone getMilestone() { - return milestone; - } - - /** - * Gets node id. - * - * @return the node id - */ - public String getNodeId() { - return nodeId; + public GHUser getAssignee() { + return assignee; } /** @@ -158,7 +164,7 @@ public GHIssueRename getRename() { /** * - * Get the {@link GHUser} person requested to review the pull request. Only present for events "review_requested", + * Get the {@link GHUser} person who requested a review. Only present for events "review_requested", * "review_request_removed", null otherwise. * * @return the GHUser @@ -169,13 +175,13 @@ public GHIssueRename getRename() { * "https://docs.github.com/en/developers/webhooks-and-events/events/issue-event-types#review_request_removed">review_request_removed */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getRequestedReviewer() { - return this.requestedReviewer; + public GHUser getReviewRequester() { + return this.reviewRequester; } /** * - * Get the {@link GHUser} person who requested a review. Only present for events "review_requested", + * Get the {@link GHUser} person requested to review the pull request. Only present for events "review_requested", * "review_request_removed", null otherwise. * * @return the GHUser @@ -186,17 +192,20 @@ public GHUser getRequestedReviewer() { * "https://docs.github.com/en/developers/webhooks-and-events/events/issue-event-types#review_request_removed">review_request_removed */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getReviewRequester() { - return this.reviewRequester; + public GHUser getRequestedReviewer() { + return this.requestedReviewer; } /** - * Gets url. + * Wrap up. * - * @return the url + * @param parent + * the parent + * @return the GH issue event */ - public String getUrl() { - return url; + GHIssueEvent wrapUp(GHIssue parent) { + this.issue = parent; + return this; } /** @@ -212,16 +221,4 @@ public String toString() { getActor().getLogin(), getCreatedAt().toString()); } - - /** - * Wrap up. - * - * @param parent - * the parent - * @return the GH issue event - */ - GHIssueEvent wrapUp(GHIssue parent) { - this.issue = parent; - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHIssueQueryBuilder.java b/src/main/java/org/kohsuke/github/GHIssueQueryBuilder.java index c7ee67c690..cf43cb6391 100644 --- a/src/main/java/org/kohsuke/github/GHIssueQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHIssueQueryBuilder.java @@ -1,6 +1,5 @@ package org.kohsuke.github; -import java.time.Instant; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -10,108 +9,6 @@ * The Class GHIssueQueryBuilder. */ public abstract class GHIssueQueryBuilder extends GHQueryBuilder { - /** - * The Class ForRepository. - */ - public static class ForRepository extends GHIssueQueryBuilder { - private final GHRepository repo; - - /** - * Instantiates a new for repository. - * - * @param repo - * the repo - */ - ForRepository(final GHRepository repo) { - super(repo.root()); - this.repo = repo; - } - - /** - * Assignee gh issue query builder. - * - * @param assignee - * the assignee - * @return the gh issue query builder - */ - public ForRepository assignee(String assignee) { - req.with("assignee", assignee); - return this; - } - - /** - * Creator gh issue query builder. - * - * @param creator - * the creator - * @return the gh issue query builder - */ - public ForRepository creator(String creator) { - req.with("creator", creator); - return this; - } - - /** - * Gets the api url. - * - * @return the api url - */ - @Override - public String getApiUrl() { - return repo.getApiTailUrl("issues"); - } - - /** - * List. - * - * @return the paged iterable - */ - @Override - public PagedIterable list() { - return req.withUrlPath(getApiUrl()).toIterable(GHIssue[].class, item -> item.wrap(repo)); - } - - /** - * Mentioned gh issue query builder. - * - * @param mentioned - * the mentioned - * @return the gh issue query builder - */ - public ForRepository mentioned(String mentioned) { - req.with("mentioned", mentioned); - return this; - } - - /** - * Milestone gh issue query builder. - *

- * The milestone must be either an integer (the milestone number), the string * (issues with any milestone) or - * the string none (issues without milestone). - * - * @param milestone - * the milestone - * @return the gh issue request query builder - */ - public ForRepository milestone(String milestone) { - req.with("milestone", milestone); - return this; - } - } - - /** - * The enum Sort. - */ - public enum Sort { - - /** The comments. */ - COMMENTS, - /** The created. */ - CREATED, - /** The updated. */ - UPDATED - } - private final List labels = new ArrayList<>(); /** @@ -125,24 +22,17 @@ public enum Sort { } /** - * Direction gh issue query builder. + * State gh issue query builder. * - * @param direction - * the direction + * @param state + * the state * @return the gh issue query builder */ - public GHIssueQueryBuilder direction(GHDirection direction) { - req.with("direction", direction); + public GHIssueQueryBuilder state(GHIssueState state) { + req.with("state", state); return this; } - /** - * Gets the api url. - * - * @return the api url - */ - public abstract String getApiUrl(); - /** * Labels gh issue query builder. * @@ -159,28 +49,27 @@ public GHIssueQueryBuilder label(String label) { } /** - * Page size gh issue query builder. + * Sort gh issue query builder. * - * @param pageSize - * the page size + * @param sort + * the sort * @return the gh issue query builder */ - public GHIssueQueryBuilder pageSize(int pageSize) { - req.with("per_page", pageSize); + public GHIssueQueryBuilder sort(Sort sort) { + req.with("sort", sort); return this; } /** - * Only issues after this date will be returned. + * Direction gh issue query builder. * - * @param date - * the date + * @param direction + * the direction * @return the gh issue query builder - * @deprecated Use {@link #since(Instant)} */ - @Deprecated - public GHIssueQueryBuilder since(Date date) { - return since(GitHubClient.toInstantOrNull(date)); + public GHIssueQueryBuilder direction(GHDirection direction) { + req.with("direction", direction); + return this; } /** @@ -190,8 +79,8 @@ public GHIssueQueryBuilder since(Date date) { * the date * @return the gh issue query builder */ - public GHIssueQueryBuilder since(Instant date) { - req.with("since", GitHubClient.printInstant(date)); + public GHIssueQueryBuilder since(Date date) { + req.with("since", GitHubClient.printDate(date)); return this; } @@ -207,26 +96,123 @@ public GHIssueQueryBuilder since(long timestamp) { } /** - * Sort gh issue query builder. + * Page size gh issue query builder. * - * @param sort - * the sort + * @param pageSize + * the page size * @return the gh issue query builder */ - public GHIssueQueryBuilder sort(Sort sort) { - req.with("sort", sort); + public GHIssueQueryBuilder pageSize(int pageSize) { + req.with("per_page", pageSize); return this; } /** - * State gh issue query builder. + * The enum Sort. + */ + public enum Sort { + + /** The created. */ + CREATED, + /** The updated. */ + UPDATED, + /** The comments. */ + COMMENTS + } + + /** + * Gets the api url. * - * @param state - * the state - * @return the gh issue query builder + * @return the api url */ - public GHIssueQueryBuilder state(GHIssueState state) { - req.with("state", state); - return this; + public abstract String getApiUrl(); + + /** + * The Class ForRepository. + */ + public static class ForRepository extends GHIssueQueryBuilder { + private final GHRepository repo; + + /** + * Instantiates a new for repository. + * + * @param repo + * the repo + */ + ForRepository(final GHRepository repo) { + super(repo.root()); + this.repo = repo; + } + + /** + * Milestone gh issue query builder. + *

+ * The milestone must be either an integer (the milestone number), the string * (issues with any milestone) or + * the string none (issues without milestone). + * + * @param milestone + * the milestone + * @return the gh issue request query builder + */ + public ForRepository milestone(String milestone) { + req.with("milestone", milestone); + return this; + } + + /** + * Assignee gh issue query builder. + * + * @param assignee + * the assignee + * @return the gh issue query builder + */ + public ForRepository assignee(String assignee) { + req.with("assignee", assignee); + return this; + } + + /** + * Creator gh issue query builder. + * + * @param creator + * the creator + * @return the gh issue query builder + */ + public ForRepository creator(String creator) { + req.with("creator", creator); + return this; + } + + /** + * Mentioned gh issue query builder. + * + * @param mentioned + * the mentioned + * @return the gh issue query builder + */ + public ForRepository mentioned(String mentioned) { + req.with("mentioned", mentioned); + return this; + } + + /** + * Gets the api url. + * + * @return the api url + */ + @Override + public String getApiUrl() { + return repo.getApiTailUrl("issues"); + } + + /** + * List. + * + * @return the paged iterable + */ + @Override + public PagedIterable list() { + return req.withUrlPath(getApiUrl()).toIterable(GHIssue[].class, item -> item.wrap(repo)); + } } } diff --git a/src/main/java/org/kohsuke/github/GHIssueRename.java b/src/main/java/org/kohsuke/github/GHIssueRename.java index 79b8042a2e..cd20c86a1d 100644 --- a/src/main/java/org/kohsuke/github/GHIssueRename.java +++ b/src/main/java/org/kohsuke/github/GHIssueRename.java @@ -10,15 +10,15 @@ */ public class GHIssueRename { - private String from = ""; - - private String to = ""; /** * Create default GHIssueRename instance */ public GHIssueRename() { } + private String from = ""; + private String to = ""; + /** * Old issue name. * diff --git a/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java b/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java index 3967691ac3..95a266847d 100644 --- a/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java @@ -11,33 +11,6 @@ */ public class GHIssueSearchBuilder extends GHSearchBuilder { - /** - * The enum Sort. - */ - public enum Sort { - - /** The comments. */ - COMMENTS, - /** The created. */ - CREATED, - /** The updated. */ - UPDATED - } - - @SuppressFBWarnings( - value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, - justification = "JSON API") - private static class IssueSearchResult extends SearchResult { - private GHIssue[] items; - - @Override - GHIssue[] getItems(GitHub root) { - for (GHIssue i : items) { - } - return items; - } - } - /** * Instantiates a new GH issue search builder. * @@ -49,21 +22,37 @@ GHIssue[] getItems(GitHub root) { } /** - * Is closed gh issue search builder. + * Search terms. + * + * @param term + * the term + * @return the GH issue search builder + */ + public GHIssueSearchBuilder q(String term) { + super.q(term); + return this; + } + + /** + * Mentions gh issue search builder. * + * @param u + * the u * @return the gh issue search builder */ - public GHIssueSearchBuilder isClosed() { - return q("is:closed"); + public GHIssueSearchBuilder mentions(GHUser u) { + return mentions(u.getLogin()); } /** - * Is merged gh issue search builder. + * Mentions gh issue search builder. * + * @param login + * the login * @return the gh issue search builder */ - public GHIssueSearchBuilder isMerged() { - return q("is:merged"); + public GHIssueSearchBuilder mentions(String login) { + return q("mentions:" + login); } /** @@ -76,25 +65,21 @@ public GHIssueSearchBuilder isOpen() { } /** - * Mentions gh issue search builder. + * Is closed gh issue search builder. * - * @param u - * the u * @return the gh issue search builder */ - public GHIssueSearchBuilder mentions(GHUser u) { - return mentions(u.getLogin()); + public GHIssueSearchBuilder isClosed() { + return q("is:closed"); } /** - * Mentions gh issue search builder. + * Is merged gh issue search builder. * - * @param login - * the login * @return the gh issue search builder */ - public GHIssueSearchBuilder mentions(String login) { - return q("mentions:" + login); + public GHIssueSearchBuilder isMerged() { + return q("is:merged"); } /** @@ -109,18 +94,6 @@ public GHIssueSearchBuilder order(GHDirection v) { return this; } - /** - * Search terms. - * - * @param term - * the term - * @return the GH issue search builder - */ - public GHIssueSearchBuilder q(String term) { - super.q(term); - return this; - } - /** * Sort gh issue search builder. * @@ -133,6 +106,33 @@ public GHIssueSearchBuilder sort(Sort sort) { return this; } + /** + * The enum Sort. + */ + public enum Sort { + + /** The comments. */ + COMMENTS, + /** The created. */ + CREATED, + /** The updated. */ + UPDATED + } + + @SuppressFBWarnings( + value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, + justification = "JSON API") + private static class IssueSearchResult extends SearchResult { + private GHIssue[] items; + + @Override + GHIssue[] getItems(GitHub root) { + for (GHIssue i : items) { + } + return items; + } + } + /** * Gets the api url. * diff --git a/src/main/java/org/kohsuke/github/GHIssueState.java b/src/main/java/org/kohsuke/github/GHIssueState.java index 9eabf43ef4..17a69251e2 100644 --- a/src/main/java/org/kohsuke/github/GHIssueState.java +++ b/src/main/java/org/kohsuke/github/GHIssueState.java @@ -32,10 +32,10 @@ */ public enum GHIssueState { - /** The all. */ - ALL, + /** The open. */ + OPEN, /** The closed. */ CLOSED, - /** The open. */ - OPEN + /** The all. */ + ALL } diff --git a/src/main/java/org/kohsuke/github/GHIssueStateReason.java b/src/main/java/org/kohsuke/github/GHIssueStateReason.java index 44acdef000..229af9f6ec 100644 --- a/src/main/java/org/kohsuke/github/GHIssueStateReason.java +++ b/src/main/java/org/kohsuke/github/GHIssueStateReason.java @@ -11,9 +11,6 @@ public enum GHIssueStateReason { /** Closed as not planned **/ NOT_PLANNED, - /** Re-opened **/ - REOPENED, - /** Uknown **/ UNKNOWN } diff --git a/src/main/java/org/kohsuke/github/GHKey.java b/src/main/java/org/kohsuke/github/GHKey.java index 812183eff9..d0e90a2032 100644 --- a/src/main/java/org/kohsuke/github/GHKey.java +++ b/src/main/java/org/kohsuke/github/GHKey.java @@ -14,8 +14,11 @@ @SuppressFBWarnings(value = "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", justification = "JSON API") public class GHKey extends GitHubInteractiveObject { - /** The id. */ - protected int id; + /** + * Create default GHKey instance + */ + public GHKey() { + } /** The title. */ protected String url, key, title; @@ -23,21 +26,8 @@ public class GHKey extends GitHubInteractiveObject { /** The verified. */ protected boolean verified; - /** - * Create default GHKey instance - */ - public GHKey() { - } - - /** - * Delete the GHKey - * - * @throws IOException - * the io exception - */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(String.format("/user/keys/%d", id)).send(); - } + /** The id. */ + protected int id; /** * Gets id. @@ -92,4 +82,14 @@ public boolean isVerified() { public String toString() { return new ToStringBuilder(this).append("title", title).append("id", id).append("key", key).toString(); } + + /** + * Delete the GHKey + * + * @throws IOException + * the io exception + */ + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(String.format("/user/keys/%d", id)).send(); + } } diff --git a/src/main/java/org/kohsuke/github/GHLabel.java b/src/main/java/org/kohsuke/github/GHLabel.java index dd3c44523e..6b77b8bfa4 100644 --- a/src/main/java/org/kohsuke/github/GHLabel.java +++ b/src/main/java/org/kohsuke/github/GHLabel.java @@ -24,41 +24,115 @@ */ public class GHLabel extends GitHubInteractiveObject { + private long id; + private String nodeId; + @JsonProperty("default") + private boolean default_; + + @Nonnull + private String url, name, color; + + @CheckForNull + private String description; + + @JsonCreator + private GHLabel(@JacksonInject @Nonnull GitHub root) { + url = ""; + name = ""; + color = ""; + description = null; + } + /** - * A {@link GHLabelBuilder} that creates a new {@link GHLabel} + * Gets the api root. * - * Consumer must call {@link Creator#done()} to create the new instance. + * @return the api root */ - @BetaApi - public static class Creator extends GHLabelBuilder { - private Creator(@Nonnull GHRepository repository) { - super(Creator.class, repository.root(), null); - requester.method("POST").withUrlPath(repository.getApiTailUrl("labels")); - } + @Nonnull + GitHub getApiRoot() { + return Objects.requireNonNull(root()); } + /** - * A {@link GHLabelBuilder} that updates a single property per request + * Gets id. * - * {@link Setter#done()} is called automatically after the property is set. + * @return the id */ - @BetaApi - public static class Setter extends GHLabelBuilder { - private Setter(@Nonnull GHLabel base) { - super(GHLabel.class, base.getApiRoot(), base); - requester.method("PATCH").setRawUrlPath(base.getUrl()); - } + public long getId() { + return id; } + /** - * A {@link GHLabelBuilder} that allows multiple properties to be updated per request. + * Gets node id. * - * Consumer must call {@link Updater#done()} to commit changes. + * @return the node id. */ - @BetaApi - public static class Updater extends GHLabelBuilder { - private Updater(@Nonnull GHLabel base) { - super(Updater.class, base.getApiRoot(), base); - requester.method("PATCH").setRawUrlPath(base.getUrl()); + public String getNodeId() { + return nodeId; + } + + /** + * Gets url. + * + * @return the url + */ + @Nonnull + public String getUrl() { + return url; + } + + /** + * Gets name. + * + * @return the name + */ + @Nonnull + public String getName() { + return name; + } + + /** + * Color code without leading '#', such as 'f29513'. + * + * @return the color + */ + @Nonnull + public String getColor() { + return color; + } + + /** + * Purpose of Label. + * + * @return the description + */ + @CheckForNull + public String getDescription() { + return description; + } + + /** + * If the label is one of the default labels created by GitHub automatically. + * + * @return true if the label is a default one + */ + public boolean isDefault() { + return default_; + } + + /** + * To names. + * + * @param labels + * the labels + * @return the collection + */ + static Collection toNames(Collection labels) { + List r = new ArrayList<>(); + for (GHLabel l : labels) { + r.add(l.getName()); } + return r; } /** @@ -69,9 +143,11 @@ private Updater(@Nonnull GHLabel base) { * @param repository * the repository in which the label will be created. * @return a {@link Creator} + * @throws IOException + * the io exception */ @BetaApi - static Creator create(GHRepository repository) { + static Creator create(GHRepository repository) throws IOException { return new Creator(repository); } @@ -100,8 +176,10 @@ static GHLabel read(@Nonnull GHRepository repository, @Nonnull String name) thro * @param repository * the repository to read from * @return iterable of all labels + * @throws IOException + * the io exception */ - static PagedIterable readAll(@Nonnull final GHRepository repository) { + static PagedIterable readAll(@Nonnull final GHRepository repository) throws IOException { return repository.root() .createRequest() .withUrlPath(repository.getApiTailUrl("labels")) @@ -110,39 +188,25 @@ static PagedIterable readAll(@Nonnull final GHRepository repository) { } /** - * To names. + * Begins a batch update * - * @param labels - * the labels - * @return the collection + * Consumer must call {@link Updater#done()} to commit changes. + * + * @return a {@link Updater} */ - static Collection toNames(Collection labels) { - List r = new ArrayList<>(); - for (GHLabel l : labels) { - r.add(l.getName()); - } - return r; + @BetaApi + public Updater update() { + return new Updater(this); } - @CheckForNull - private String description; - - private long id; - - @JsonProperty("default") - private boolean isDefault; - - private String nodeId; - - @Nonnull - private String url, name, color; - - @JsonCreator - private GHLabel(@JacksonInject @Nonnull GitHub root) { - url = ""; - name = ""; - color = ""; - description = null; + /** + * Begins a single property update. + * + * @return a {@link Setter} + */ + @BetaApi + public Setter set() { + return new Setter(this); } /** @@ -173,64 +237,6 @@ public boolean equals(final Object o) { && Objects.equals(color, ghLabel.color) && Objects.equals(description, ghLabel.description); } - /** - * Color code without leading '#', such as 'f29513'. - * - * @return the color - */ - @Nonnull - public String getColor() { - return color; - } - - /** - * Purpose of Label. - * - * @return the description - */ - @CheckForNull - public String getDescription() { - return description; - } - - /** - * Gets id. - * - * @return the id - */ - public long getId() { - return id; - } - - /** - * Gets name. - * - * @return the name - */ - @Nonnull - public String getName() { - return name; - } - - /** - * Gets node id. - * - * @return the node id. - */ - public String getNodeId() { - return nodeId; - } - - /** - * Gets url. - * - * @return the url - */ - @Nonnull - public String getUrl() { - return url; - } - /** * Hash code. * @@ -242,44 +248,42 @@ public int hashCode() { } /** - * If the label is one of the default labels created by GitHub automatically. - * - * @return true if the label is a default one - */ - public boolean isDefault() { - return isDefault; - } - - /** - * Begins a single property update. + * A {@link GHLabelBuilder} that updates a single property per request * - * @return a {@link Setter} + * {@link Setter#done()} is called automatically after the property is set. */ @BetaApi - public Setter set() { - return new Setter(this); + public static class Setter extends GHLabelBuilder { + private Setter(@Nonnull GHLabel base) { + super(GHLabel.class, base.getApiRoot(), base); + requester.method("PATCH").setRawUrlPath(base.getUrl()); + } } /** - * Begins a batch update + * A {@link GHLabelBuilder} that allows multiple properties to be updated per request. * * Consumer must call {@link Updater#done()} to commit changes. - * - * @return a {@link Updater} */ @BetaApi - public Updater update() { - return new Updater(this); + public static class Updater extends GHLabelBuilder { + private Updater(@Nonnull GHLabel base) { + super(Updater.class, base.getApiRoot(), base); + requester.method("PATCH").setRawUrlPath(base.getUrl()); + } } /** - * Gets the api root. + * A {@link GHLabelBuilder} that creates a new {@link GHLabel} * - * @return the api root + * Consumer must call {@link Creator#done()} to create the new instance. */ - @Nonnull - GitHub getApiRoot() { - return Objects.requireNonNull(root()); + @BetaApi + public static class Creator extends GHLabelBuilder { + private Creator(@Nonnull GHRepository repository) { + super(Creator.class, repository.root(), null); + requester.method("POST").withUrlPath(repository.getApiTailUrl("labels")); + } } } diff --git a/src/main/java/org/kohsuke/github/GHLabelBuilder.java b/src/main/java/org/kohsuke/github/GHLabelBuilder.java index ffbcb3fbf5..3803a7de8e 100644 --- a/src/main/java/org/kohsuke/github/GHLabelBuilder.java +++ b/src/main/java/org/kohsuke/github/GHLabelBuilder.java @@ -10,7 +10,7 @@ * The Class GHLabelBuilder. * * @param - * Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If {@code S} + * Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If {@link S} * the same as {@link GHLabel}, this builder will commit changes after each call to * {@link #with(String, Object)}. */ @@ -21,7 +21,7 @@ class GHLabelBuilder extends AbstractBuilder { * * @param intermediateReturnType * Intermediate return type for this builder returned by calls to {@link #with(String, Object)}. If - * {@code S} the same as {@link GHLabel}, this builder will commit changes after each call to + * {@link S} the same as {@link GHLabel}, this builder will commit changes after each call to * {@link #with(String, Object)}. * @param root * the GitHub instance to which updates will be sent @@ -41,7 +41,7 @@ protected GHLabelBuilder(@Nonnull Class intermediateReturnType, } /** - * Color. + * Name. * * @param value * the value @@ -51,12 +51,12 @@ protected GHLabelBuilder(@Nonnull Class intermediateReturnType, */ @Nonnull @BetaApi - public S color(String value) throws IOException { - return with("color", value); + public S name(String value) throws IOException { + return with("name", value); } /** - * Description. + * Color. * * @param value * the value @@ -66,12 +66,12 @@ public S color(String value) throws IOException { */ @Nonnull @BetaApi - public S description(String value) throws IOException { - return with("description", value); + public S color(String value) throws IOException { + return with("color", value); } /** - * Name. + * Description. * * @param value * the value @@ -81,7 +81,7 @@ public S description(String value) throws IOException { */ @Nonnull @BetaApi - public S name(String value) throws IOException { - return with("name", value); + public S description(String value) throws IOException { + return with("description", value); } } diff --git a/src/main/java/org/kohsuke/github/GHLabelChanges.java b/src/main/java/org/kohsuke/github/GHLabelChanges.java index c76058e3dc..a3880dcbf6 100644 --- a/src/main/java/org/kohsuke/github/GHLabelChanges.java +++ b/src/main/java/org/kohsuke/github/GHLabelChanges.java @@ -12,35 +12,21 @@ public class GHLabelChanges { /** - * Wrapper for changed values. + * Create default GHLabelChanges instance */ - public static class GHFrom { - - private String from; - - /** - * Create default GHFrom instance - */ - public GHFrom() { - } - - /** - * Previous value that was changed. - * - * @return previous value - */ - public String getFrom() { - return from; - } + public GHLabelChanges() { } - private GHFrom color; private GHFrom name; + private GHFrom color; /** - * Create default GHLabelChanges instance + * Old label name. + * + * @return old label name (or null if not changed) */ - public GHLabelChanges() { + public GHFrom getName() { + return name; } /** @@ -53,11 +39,25 @@ public GHFrom getColor() { } /** - * Old label name. - * - * @return old label name (or null if not changed) + * Wrapper for changed values. */ - public GHFrom getName() { - return name; + public static class GHFrom { + + /** + * Create default GHFrom instance + */ + public GHFrom() { + } + + private String from; + + /** + * Previous value that was changed. + * + * @return previous value + */ + public String getFrom() { + return from; + } } } diff --git a/src/main/java/org/kohsuke/github/GHLicense.java b/src/main/java/org/kohsuke/github/GHLicense.java index 71aff84609..9a66ad3a98 100644 --- a/src/main/java/org/kohsuke/github/GHLicense.java +++ b/src/main/java/org/kohsuke/github/GHLicense.java @@ -47,72 +47,81 @@ justification = "JSON API") public class GHLicense extends GHObject { + /** + * Create default GHLicense instance + */ + public GHLicense() { + } + + /** The name. */ + // these fields are always present, even in the short form + protected String key, name, spdxId; + /** The featured. */ // the rest is only after populated protected Boolean featured; - /** The forbidden. */ - protected List forbidden = new ArrayList(); - /** The body. */ - protected String htmlUrl, description, category, implementation, body; + protected String html_url, description, category, implementation, body; - /** The name. */ - // these fields are always present, even in the short form - protected String key, name, spdxId; + /** The required. */ + protected List required = new ArrayList(); /** The permitted. */ protected List permitted = new ArrayList(); - /** The required. */ - protected List required = new ArrayList(); + /** The forbidden. */ + protected List forbidden = new ArrayList(); /** - * Create default GHLicense instance + * Gets key. + * + * @return a mnemonic for the license */ - public GHLicense() { + public String getKey() { + return key; } /** - * Equals. + * Gets name. * - * @param o - * the o - * @return true, if successful + * @return the license name */ - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof GHLicense)) - return false; + public String getName() { + return name; + } - GHLicense that = (GHLicense) o; - return Objects.equals(getUrl(), that.getUrl()); + /** + * Gets SPDX ID. + * + * @return the spdx id + */ + public String getSpdxId() { + return spdxId; } /** - * Gets body. + * Featured licenses are bold in the new repository drop-down. * - * @return the body + * @return True if the license is featured, false otherwise * @throws IOException * the io exception */ - public String getBody() throws IOException { + public Boolean isFeatured() throws IOException { populate(); - return body; + return featured; } /** - * Gets category. + * Gets the html url. * - * @return the category + * @return the html url * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public String getCategory() throws IOException { + public URL getHtmlUrl() throws IOException { populate(); - return category; + return GitHubClient.parseURL(html_url); } /** @@ -128,27 +137,15 @@ public String getDescription() throws IOException { } /** - * Gets forbidden. + * Gets category. * - * @return the forbidden + * @return the category * @throws IOException * the io exception */ - public List getForbidden() throws IOException { - populate(); - return Collections.unmodifiableList(forbidden); - } - - /** - * Gets the html url. - * - * @return the html url - * @throws IOException - * Signals that an I/O exception has occurred. - */ - public URL getHtmlUrl() throws IOException { + public String getCategory() throws IOException { populate(); - return GitHubClient.parseURL(htmlUrl); + return category; } /** @@ -164,21 +161,15 @@ public String getImplementation() throws IOException { } /** - * Gets key. - * - * @return a mnemonic for the license - */ - public String getKey() { - return key; - } - - /** - * Gets name. + * Gets required. * - * @return the license name + * @return the required + * @throws IOException + * the io exception */ - public String getName() { - return name; + public List getRequired() throws IOException { + populate(); + return Collections.unmodifiableList(required); } /** @@ -194,46 +185,27 @@ public List getPermitted() throws IOException { } /** - * Gets required. + * Gets forbidden. * - * @return the required + * @return the forbidden * @throws IOException * the io exception */ - public List getRequired() throws IOException { + public List getForbidden() throws IOException { populate(); - return Collections.unmodifiableList(required); - } - - /** - * Gets SPDX ID. - * - * @return the spdx id - */ - public String getSpdxId() { - return spdxId; - } - - /** - * Hash code. - * - * @return the int - */ - @Override - public int hashCode() { - return Objects.hashCode(getUrl()); + return Collections.unmodifiableList(forbidden); } /** - * Featured licenses are bold in the new repository drop-down. + * Gets body. * - * @return True if the license is featured, false otherwise + * @return the body * @throws IOException * the io exception */ - public Boolean isFeatured() throws IOException { + public String getBody() throws IOException { populate(); - return featured; + return body; } /** @@ -257,4 +229,32 @@ protected synchronized void populate() throws IOException { root().createRequest().setRawUrlPath(url.toString()).fetchInto(this); } } + + /** + * Equals. + * + * @param o + * the o + * @return true, if successful + */ + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof GHLicense)) + return false; + + GHLicense that = (GHLicense) o; + return Objects.equals(getUrl(), that.getUrl()); + } + + /** + * Hash code. + * + * @return the int + */ + @Override + public int hashCode() { + return Objects.hashCode(getUrl()); + } } diff --git a/src/main/java/org/kohsuke/github/GHMarketplaceAccount.java b/src/main/java/org/kohsuke/github/GHMarketplaceAccount.java index ac872ee8ba..df0261e880 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplaceAccount.java +++ b/src/main/java/org/kohsuke/github/GHMarketplaceAccount.java @@ -13,26 +13,26 @@ */ public class GHMarketplaceAccount extends GitHubInteractiveObject { - private String email; - - private long id; - private String login; - private String organizationBillingEmail; - private GHMarketplaceAccountType type; - private String url; /** * Create default GHMarketplaceAccount instance */ public GHMarketplaceAccount() { } + private String url; + private long id; + private String login; + private String email; + private String organizationBillingEmail; + private GHMarketplaceAccountType type; + /** - * Gets email. + * Gets url. * - * @return the email + * @return the url */ - public String getEmail() { - return email; + public URL getUrl() { + return GitHubClient.parseURL(url); } /** @@ -53,6 +53,15 @@ public String getLogin() { return login; } + /** + * Gets email. + * + * @return the email + */ + public String getEmail() { + return email; + } + /** * Gets organization billing email. * @@ -62,6 +71,15 @@ public String getOrganizationBillingEmail() { return organizationBillingEmail; } + /** + * Gets type. + * + * @return the type + */ + public GHMarketplaceAccountType getType() { + return type; + } + /** * Shows whether the user or organization account actively subscribes to a plan listed by the authenticated GitHub * App. When someone submits a plan change that won't be processed until the end of their billing cycle, you will @@ -83,22 +101,4 @@ public GHMarketplaceAccountPlan getPlan() throws IOException { return new GHMarketplacePlanForAccountBuilder(root(), this.id).createRequest(); } - /** - * Gets type. - * - * @return the type - */ - public GHMarketplaceAccountType getType() { - return type; - } - - /** - * Gets url. - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(url); - } - } diff --git a/src/main/java/org/kohsuke/github/GHMarketplaceAccountPlan.java b/src/main/java/org/kohsuke/github/GHMarketplaceAccountPlan.java index c53a1f8a5a..c780aa4dde 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplaceAccountPlan.java +++ b/src/main/java/org/kohsuke/github/GHMarketplaceAccountPlan.java @@ -11,17 +11,17 @@ */ public class GHMarketplaceAccountPlan extends GHMarketplaceAccount { - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private GHMarketplacePendingChange marketplacePendingChange; - - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private GHMarketplacePurchase marketplacePurchase; /** * Create default GHMarketplaceAccountPlan instance */ public GHMarketplaceAccountPlan() { } + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private GHMarketplacePendingChange marketplacePendingChange; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private GHMarketplacePurchase marketplacePurchase; + /** * Gets marketplace pending change. * diff --git a/src/main/java/org/kohsuke/github/GHMarketplaceListAccountBuilder.java b/src/main/java/org/kohsuke/github/GHMarketplaceListAccountBuilder.java index 63e53d2e3b..1e061a36c3 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplaceListAccountBuilder.java +++ b/src/main/java/org/kohsuke/github/GHMarketplaceListAccountBuilder.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import java.io.IOException; + // TODO: Auto-generated Javadoc /** * Returns any accounts associated with a plan, including free plans. @@ -8,18 +10,7 @@ * @see GHMarketplacePlan#listAccounts() */ public class GHMarketplaceListAccountBuilder extends GitHubInteractiveObject { - /** - * The enum Sort. - */ - public enum Sort { - - /** The created. */ - CREATED, - /** The updated. */ - UPDATED - } private final Requester builder; - private final long planId; /** @@ -37,17 +28,17 @@ public enum Sort { } /** - * List any accounts associated with the plan specified on construction with all the order/sort parameters set. - *

- * GitHub Apps must use a JWT to access this endpoint. + * Sorts the GitHub accounts by the date they were created or last updated. Can be one of created or updated. *

- * OAuth Apps must use basic authentication with their client ID and client secret to access this endpoint. + * If omitted, the default sorting strategy will be "CREATED" * - * @return a paged iterable instance of GHMarketplaceAccountPlan + * @param sort + * the sort strategy + * @return a GHMarketplaceListAccountBuilder */ - public PagedIterable createRequest() { - return builder.withUrlPath(String.format("/marketplace_listing/plans/%d/accounts", this.planId)) - .toIterable(GHMarketplaceAccountPlan[].class, null); + public GHMarketplaceListAccountBuilder sort(Sort sort) { + this.builder.with("sort", sort); + return this; } /** @@ -63,17 +54,30 @@ public GHMarketplaceListAccountBuilder direction(GHDirection direction) { } /** - * Sorts the GitHub accounts by the date they were created or last updated. Can be one of created or updated. + * The enum Sort. + */ + public enum Sort { + + /** The created. */ + CREATED, + /** The updated. */ + UPDATED + } + + /** + * List any accounts associated with the plan specified on construction with all the order/sort parameters set. *

- * If omitted, the default sorting strategy will be "CREATED" + * GitHub Apps must use a JWT to access this endpoint. + *

+ * OAuth Apps must use basic authentication with their client ID and client secret to access this endpoint. * - * @param sort - * the sort strategy - * @return a GHMarketplaceListAccountBuilder + * @return a paged iterable instance of GHMarketplaceAccountPlan + * @throws IOException + * on error */ - public GHMarketplaceListAccountBuilder sort(Sort sort) { - this.builder.with("sort", sort); - return this; + public PagedIterable createRequest() throws IOException { + return builder.withUrlPath(String.format("/marketplace_listing/plans/%d/accounts", this.planId)) + .toIterable(GHMarketplaceAccountPlan[].class, null); } } diff --git a/src/main/java/org/kohsuke/github/GHMarketplacePendingChange.java b/src/main/java/org/kohsuke/github/GHMarketplacePendingChange.java index 39fcdf4f8b..d91e6e5417 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplacePendingChange.java +++ b/src/main/java/org/kohsuke/github/GHMarketplacePendingChange.java @@ -1,9 +1,7 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -15,29 +13,19 @@ */ public class GHMarketplacePendingChange extends GitHubInteractiveObject { - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private String effectiveDate; - - private long id; - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private GHMarketplacePlan plan; - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private Long unitCount; /** * Create default GHMarketplacePendingChange instance */ public GHMarketplacePendingChange() { } - /** - * Gets effective date. - * - * @return the effective date - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getEffectiveDate() { - return GitHubClient.parseInstant(effectiveDate); - } + private long id; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private Long unitCount; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private GHMarketplacePlan plan; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private String effectiveDate; /** * Gets id. @@ -48,6 +36,15 @@ public long getId() { return id; } + /** + * Gets unit count. + * + * @return the unit count + */ + public Long getUnitCount() { + return unitCount; + } + /** * Gets plan. * @@ -58,12 +55,12 @@ public GHMarketplacePlan getPlan() { } /** - * Gets unit count. + * Gets effective date. * - * @return the unit count + * @return the effective date */ - public Long getUnitCount() { - return unitCount; + public Date getEffectiveDate() { + return GitHubClient.parseDate(effectiveDate); } } diff --git a/src/main/java/org/kohsuke/github/GHMarketplacePlan.java b/src/main/java/org/kohsuke/github/GHMarketplacePlan.java index 03cc87c662..43bcfe3be1 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplacePlan.java +++ b/src/main/java/org/kohsuke/github/GHMarketplacePlan.java @@ -15,25 +15,34 @@ */ public class GHMarketplacePlan extends GitHubInteractiveObject { - private String accountsUrl; + /** + * Create default GHMarketplacePlan instance + */ + public GHMarketplacePlan() { + } - private List bullets; - private String description; - @JsonProperty("has_free_trial") - private boolean freeTrial; // JavaBeans Spec 1.01 section 8.3.2 forces us to have is + private String url; + private String accountsUrl; private long id; - private long monthlyPriceInCents; - private String name; private long number; + private String name; + private String description; + private long monthlyPriceInCents; + private long yearlyPriceInCents; private GHMarketplacePriceModel priceModel; - private String state; + @JsonProperty("has_free_trial") + private boolean freeTrial; // JavaBeans Spec 1.01 section 8.3.2 forces us to have is private String unitName; - private String url; - private long yearlyPriceInCents; + private String state; + private List bullets; + /** - * Create default GHMarketplacePlan instance + * Gets url. + * + * @return the url */ - public GHMarketplacePlan() { + public URL getUrl() { + return GitHubClient.parseURL(url); } /** @@ -46,57 +55,57 @@ public String getAccountsUrl() { } /** - * Gets bullets. + * Gets id. * - * @return the bullets + * @return the id */ - public List getBullets() { - return Collections.unmodifiableList(bullets); + public long getId() { + return id; } /** - * Gets description. + * Gets number. * - * @return the description + * @return the number */ - public String getDescription() { - return description; + public long getNumber() { + return number; } /** - * Gets id. + * Gets name. * - * @return the id + * @return the name */ - public long getId() { - return id; + public String getName() { + return name; } /** - * Gets monthly price in cents. + * Gets description. * - * @return the monthly price in cents + * @return the description */ - public long getMonthlyPriceInCents() { - return monthlyPriceInCents; + public String getDescription() { + return description; } /** - * Gets name. + * Gets monthly price in cents. * - * @return the name + * @return the monthly price in cents */ - public String getName() { - return name; + public long getMonthlyPriceInCents() { + return monthlyPriceInCents; } /** - * Gets number. + * Gets yearly price in cents. * - * @return the number + * @return the yearly price in cents */ - public long getNumber() { - return number; + public long getYearlyPriceInCents() { + return yearlyPriceInCents; } /** @@ -109,12 +118,12 @@ public GHMarketplacePriceModel getPriceModel() { } /** - * Gets state. + * Is free trial boolean. * - * @return the state + * @return the boolean */ - public String getState() { - return state; + public boolean isFreeTrial() { + return freeTrial; } /** @@ -127,30 +136,21 @@ public String getUnitName() { } /** - * Gets url. - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(url); - } - - /** - * Gets yearly price in cents. + * Gets state. * - * @return the yearly price in cents + * @return the state */ - public long getYearlyPriceInCents() { - return yearlyPriceInCents; + public String getState() { + return state; } /** - * Is free trial boolean. + * Gets bullets. * - * @return the boolean + * @return the bullets */ - public boolean isFreeTrial() { - return freeTrial; + public List getBullets() { + return Collections.unmodifiableList(bullets); } /** diff --git a/src/main/java/org/kohsuke/github/GHMarketplacePlanForAccountBuilder.java b/src/main/java/org/kohsuke/github/GHMarketplacePlanForAccountBuilder.java index 55715a85ef..e5167f31ac 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplacePlanForAccountBuilder.java +++ b/src/main/java/org/kohsuke/github/GHMarketplacePlanForAccountBuilder.java @@ -11,8 +11,8 @@ * @see GitHub#listMarketplacePlans() */ public class GHMarketplacePlanForAccountBuilder extends GitHubInteractiveObject { - private final long accountId; private final Requester builder; + private final long accountId; /** * Instantiates a new GH marketplace list account builder. diff --git a/src/main/java/org/kohsuke/github/GHMarketplacePriceModel.java b/src/main/java/org/kohsuke/github/GHMarketplacePriceModel.java index 57cdcc9b7f..a41cfc651c 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplacePriceModel.java +++ b/src/main/java/org/kohsuke/github/GHMarketplacePriceModel.java @@ -11,12 +11,12 @@ */ public enum GHMarketplacePriceModel { - /** The flat rate. */ - FLAT_RATE("FLAT_RATE"), /** The free. */ FREE("FREE"), /** The per unit. */ - PER_UNIT("PER_UNIT"); + PER_UNIT("PER_UNIT"), + /** The flat rate. */ + FLAT_RATE("FLAT_RATE"); @JsonValue private final String internalName; diff --git a/src/main/java/org/kohsuke/github/GHMarketplacePurchase.java b/src/main/java/org/kohsuke/github/GHMarketplacePurchase.java index 9b6b8f1e27..a0c149e159 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplacePurchase.java +++ b/src/main/java/org/kohsuke/github/GHMarketplacePurchase.java @@ -1,9 +1,7 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -15,21 +13,21 @@ */ public class GHMarketplacePurchase extends GitHubInteractiveObject { - private String billingCycle; - - private String freeTrialEndsOn; - private String nextBillingDate; - private boolean onFreeTrial; - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private GHMarketplacePlan plan; - private Long unitCount; - private String updatedAt; /** * Create default GHMarketplacePurchase instance */ public GHMarketplacePurchase() { } + private String billingCycle; + private String nextBillingDate; + private boolean onFreeTrial; + private String freeTrialEndsOn; + private Long unitCount; + private String updatedAt; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private GHMarketplacePlan plan; + /** * Gets billing cycle. * @@ -40,32 +38,30 @@ public String getBillingCycle() { } /** - * Gets free trial ends on. + * Gets next billing date. * - * @return the free trial ends on + * @return the next billing date */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getFreeTrialEndsOn() { - return GitHubClient.parseInstant(freeTrialEndsOn); + public Date getNextBillingDate() { + return GitHubClient.parseDate(nextBillingDate); } /** - * Gets next billing date. + * Is on free trial boolean. * - * @return the next billing date + * @return the boolean */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getNextBillingDate() { - return GitHubClient.parseInstant(nextBillingDate); + public boolean isOnFreeTrial() { + return onFreeTrial; } /** - * Gets plan. + * Gets free trial ends on. * - * @return the plan + * @return the free trial ends on */ - public GHMarketplacePlan getPlan() { - return plan; + public Date getFreeTrialEndsOn() { + return GitHubClient.parseDate(freeTrialEndsOn); } /** @@ -82,17 +78,16 @@ public Long getUnitCount() { * * @return the updated at */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getUpdatedAt() { - return GitHubClient.parseInstant(updatedAt); + public Date getUpdatedAt() { + return GitHubClient.parseDate(updatedAt); } /** - * Is on free trial boolean. + * Gets plan. * - * @return the boolean + * @return the plan */ - public boolean isOnFreeTrial() { - return onFreeTrial; + public GHMarketplacePlan getPlan() { + return plan; } } diff --git a/src/main/java/org/kohsuke/github/GHMarketplaceUserPurchase.java b/src/main/java/org/kohsuke/github/GHMarketplaceUserPurchase.java index 1ad622da99..fb2b210512 100644 --- a/src/main/java/org/kohsuke/github/GHMarketplaceUserPurchase.java +++ b/src/main/java/org/kohsuke/github/GHMarketplaceUserPurchase.java @@ -1,9 +1,7 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -15,31 +13,22 @@ */ public class GHMarketplaceUserPurchase extends GitHubInteractiveObject { - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private GHMarketplaceAccount account; - - private String billingCycle; - private String freeTrialEndsOn; - private String nextBillingDate; - private boolean onFreeTrial; - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - private GHMarketplacePlan plan; - private Long unitCount; - private String updatedAt; /** * Create default GHMarketplaceUserPurchase instance */ public GHMarketplaceUserPurchase() { } - /** - * Gets account. - * - * @return the account - */ - public GHMarketplaceAccount getAccount() { - return account; - } + private String billingCycle; + private String nextBillingDate; + private boolean onFreeTrial; + private String freeTrialEndsOn; + private Long unitCount; + private String updatedAt; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private GHMarketplaceAccount account; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + private GHMarketplacePlan plan; /** * Gets billing cycle. @@ -51,32 +40,30 @@ public String getBillingCycle() { } /** - * Gets free trial ends on. + * Gets next billing date. * - * @return the free trial ends on + * @return the next billing date */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getFreeTrialEndsOn() { - return GitHubClient.parseInstant(freeTrialEndsOn); + public Date getNextBillingDate() { + return GitHubClient.parseDate(nextBillingDate); } /** - * Gets next billing date. + * Is on free trial boolean. * - * @return the next billing date + * @return the boolean */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getNextBillingDate() { - return GitHubClient.parseInstant(nextBillingDate); + public boolean isOnFreeTrial() { + return onFreeTrial; } /** - * Gets plan. + * Gets free trial ends on. * - * @return the plan + * @return the free trial ends on */ - public GHMarketplacePlan getPlan() { - return plan; + public Date getFreeTrialEndsOn() { + return GitHubClient.parseDate(freeTrialEndsOn); } /** @@ -93,17 +80,25 @@ public Long getUnitCount() { * * @return the updated at */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getUpdatedAt() { - return GitHubClient.parseInstant(updatedAt); + public Date getUpdatedAt() { + return GitHubClient.parseDate(updatedAt); } /** - * Is on free trial boolean. + * Gets account. * - * @return the boolean + * @return the account */ - public boolean isOnFreeTrial() { - return onFreeTrial; + public GHMarketplaceAccount getAccount() { + return account; + } + + /** + * Gets plan. + * + * @return the plan + */ + public GHMarketplacePlan getPlan() { + return plan; } } diff --git a/src/main/java/org/kohsuke/github/GHMemberChanges.java b/src/main/java/org/kohsuke/github/GHMemberChanges.java index 93f5043861..781753eaec 100644 --- a/src/main/java/org/kohsuke/github/GHMemberChanges.java +++ b/src/main/java/org/kohsuke/github/GHMemberChanges.java @@ -9,26 +9,34 @@ public class GHMemberChanges { /** - * Changes to role name. + * Create default GHMemberChanges instance */ - public static class FromRoleName { + public GHMemberChanges() { + } - private String to; + private FromToPermission permission; - /** - * Create default FromRoleName instance - */ - public FromRoleName() { - } + private FromRoleName roleName; - /** - * Gets the to. - * - * @return the to - */ - public String getTo() { - return to; - } + /** + * Get changes to permission. + * + * @return changes to permission + */ + public FromToPermission getPermission() { + return permission; + } + + /** + * Get changes to the role name. + *

+ * Apparently, it is recommended to use this rather than permission if defined. But it will only be defined when + * adding and not when editing. + * + * @return changes to role name + */ + public FromRoleName getRoleName() { + return roleName; } /** @@ -36,16 +44,16 @@ public String getTo() { */ public static class FromToPermission { - private String from; - - private String to; - /** * Create default FromToPermission instance */ public FromToPermission() { } + private String from; + + private String to; + /** * Gets the from. * @@ -69,34 +77,26 @@ public String getTo() { } } - private FromToPermission permission; - - private FromRoleName roleName; - /** - * Create default GHMemberChanges instance + * Changes to role name. */ - public GHMemberChanges() { - } + public static class FromRoleName { - /** - * Get changes to permission. - * - * @return changes to permission - */ - public FromToPermission getPermission() { - return permission; - } + /** + * Create default FromRoleName instance + */ + public FromRoleName() { + } - /** - * Get changes to the role name. - *

- * Apparently, it is recommended to use this rather than permission if defined. But it will only be defined when - * adding and not when editing. - * - * @return changes to role name - */ - public FromRoleName getRoleName() { - return roleName; + private String to; + + /** + * Gets the to. + * + * @return the to + */ + public String getTo() { + return to; + } } } diff --git a/src/main/java/org/kohsuke/github/GHMembership.java b/src/main/java/org/kohsuke/github/GHMembership.java index d3b39282f9..e6b7e2e09c 100644 --- a/src/main/java/org/kohsuke/github/GHMembership.java +++ b/src/main/java/org/kohsuke/github/GHMembership.java @@ -18,70 +18,42 @@ public class GHMembership extends GitHubInteractiveObject { /** - * Role of a user in an organization. - */ - public enum Role { - /** - * Organization owner. - */ - ADMIN, - /** - * Non-owner organization member. - */ - MEMBER; - } - - /** - * Whether a role is currently active or waiting for acceptance (pending). + * Create default GHMembership instance */ - public enum State { - - /** The active. */ - ACTIVE, - /** The pending. */ - PENDING; + public GHMembership() { } - /** The organization. */ - GHOrganization organization; - - /** The role. */ - String role; + /** The url. */ + String url; /** The state. */ String state; - /** The url. */ - String url; + /** The role. */ + String role; /** The user. */ GHUser user; - /** - * Create default GHMembership instance - */ - public GHMembership() { - } + /** The organization. */ + GHOrganization organization; /** - * Accepts a pending invitation to an organization. + * Gets url. * - * @throws IOException - * the io exception - * @see GHMyself#getMembership(GHOrganization) GHMyself#getMembership(GHOrganization) + * @return the url */ - public void activate() throws IOException { - root().createRequest().method("PATCH").with("state", State.ACTIVE).withUrlPath(url).fetchInto(this); + public URL getUrl() { + return GitHubClient.parseURL(url); } /** - * Gets organization. + * Gets state. * - * @return the organization + * @return the state */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHOrganization getOrganization() { - return organization; + public State getState() { + return Enum.valueOf(State.class, state.toUpperCase(Locale.ENGLISH)); } /** @@ -94,31 +66,34 @@ public Role getRole() { } /** - * Gets state. + * Gets user. * - * @return the state + * @return the user */ - public State getState() { - return Enum.valueOf(State.class, state.toUpperCase(Locale.ENGLISH)); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getUser() { + return user; } /** - * Gets url. + * Gets organization. * - * @return the url + * @return the organization */ - public URL getUrl() { - return GitHubClient.parseURL(url); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHOrganization getOrganization() { + return organization; } /** - * Gets user. + * Accepts a pending invitation to an organization. * - * @return the user + * @throws IOException + * the io exception + * @see GHMyself#getMembership(GHOrganization) GHMyself#getMembership(GHOrganization) */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getUser() { - return user; + public void activate() throws IOException { + root().createRequest().method("PATCH").with("state", State.ACTIVE).withUrlPath(url).fetchInto(this); } /** @@ -133,4 +108,29 @@ GHMembership wrap(GitHub root) { user = root.getUser(user); return this; } + + /** + * Role of a user in an organization. + */ + public enum Role { + /** + * Organization owner. + */ + ADMIN, + /** + * Non-owner organization member. + */ + MEMBER; + } + + /** + * Whether a role is currently active or waiting for acceptance (pending). + */ + public enum State { + + /** The active. */ + ACTIVE, + /** The pending. */ + PENDING; + } } diff --git a/src/main/java/org/kohsuke/github/GHMeta.java b/src/main/java/org/kohsuke/github/GHMeta.java index 7978efe697..bfa900f7eb 100644 --- a/src/main/java/org/kohsuke/github/GHMeta.java +++ b/src/main/java/org/kohsuke/github/GHMeta.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; // TODO: Auto-generated Javadoc /** @@ -13,58 +12,44 @@ * * @author Paulo Miguel Almeida * @see GitHub#getMeta() GitHub#getMeta() - * @see Get - * Meta + * @see Get Meta */ public class GHMeta { - private List actions; - - private List api; - private List dependabot; - private List git; - private List hooks; - private List importer = new ArrayList<>(); - private List packages; - private List pages; - @JsonProperty("ssh_key_fingerprints") - private Map sshKeyFingerprints; - @JsonProperty("ssh_keys") - private List sshKeys; - @JsonProperty("verifiable_password_authentication") - private boolean verifiablePasswordAuthentication; - private List web; /** * Create default GHMeta instance */ public GHMeta() { } - /** - * Gets actions. - * - * @return the actions - */ - public List getActions() { - return Collections.unmodifiableList(actions); - } + @JsonProperty("verifiable_password_authentication") + private boolean verifiablePasswordAuthentication; + private List hooks; + private List git; + private List web; + private List api; + private List pages; + private List importer = new ArrayList<>(); + private List packages; + private List actions; + private List dependabot; /** - * Gets api. + * Is verifiable password authentication boolean. * - * @return the api + * @return the boolean */ - public List getApi() { - return Collections.unmodifiableList(api); + public boolean isVerifiablePasswordAuthentication() { + return verifiablePasswordAuthentication; } /** - * Gets dependabot. + * Gets hooks. * - * @return the dependabot + * @return the hooks */ - public List getDependabot() { - return Collections.unmodifiableList(dependabot); + public List getHooks() { + return Collections.unmodifiableList(hooks); } /** @@ -77,30 +62,21 @@ public List getGit() { } /** - * Gets hooks. - * - * @return the hooks - */ - public List getHooks() { - return Collections.unmodifiableList(hooks); - } - - /** - * Gets importer. + * Gets web. * - * @return the importer + * @return the web */ - public List getImporter() { - return Collections.unmodifiableList(importer); + public List getWeb() { + return Collections.unmodifiableList(web); } /** - * Gets package. + * Gets api. * - * @return the package + * @return the api */ - public List getPackages() { - return Collections.unmodifiableList(packages); + public List getApi() { + return Collections.unmodifiableList(api); } /** @@ -113,38 +89,38 @@ public List getPages() { } /** - * Gets ssh key fingerprints. + * Gets importer. * - * @return the ssh key fingerprints + * @return the importer */ - public Map getSshKeyFingerprints() { - return Collections.unmodifiableMap(sshKeyFingerprints); + public List getImporter() { + return Collections.unmodifiableList(importer); } /** - * Gets ssh keys. + * Gets package. * - * @return the ssh keys + * @return the package */ - public List getSshKeys() { - return Collections.unmodifiableList(sshKeys); + public List getPackages() { + return Collections.unmodifiableList(packages); } /** - * Gets web. + * Gets actions. * - * @return the web + * @return the actions */ - public List getWeb() { - return Collections.unmodifiableList(web); + public List getActions() { + return Collections.unmodifiableList(actions); } /** - * Is verifiable password authentication boolean. + * Gets dependabot. * - * @return the boolean + * @return the dependabot */ - public boolean isVerifiablePasswordAuthentication() { - return verifiablePasswordAuthentication; + public List getDependabot() { + return Collections.unmodifiableList(dependabot); } } diff --git a/src/main/java/org/kohsuke/github/GHMilestone.java b/src/main/java/org/kohsuke/github/GHMilestone.java index 7cd556c8ee..eeefaf5a9b 100644 --- a/src/main/java/org/kohsuke/github/GHMilestone.java +++ b/src/main/java/org/kohsuke/github/GHMilestone.java @@ -1,11 +1,9 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Date; import java.util.Locale; @@ -17,69 +15,73 @@ */ public class GHMilestone extends GHObject { - private int closedIssues, openIssues, number; - - private String state, dueOn, title, description, htmlUrl; - - /** The closed at. */ - protected String closedAt; - /** The creator. */ - GHUser creator; - /** The owner. */ - GHRepository owner; - /** * Create default GHMilestone instance */ public GHMilestone() { } + /** The owner. */ + GHRepository owner; + + /** The creator. */ + GHUser creator; + private String state, due_on, title, description, html_url; + private int closed_issues, open_issues, number; + + /** The closed at. */ + protected String closed_at; + /** - * Closes this milestone. + * Gets owner. * - * @throws IOException - * the io exception + * @return the owner */ - public void close() throws IOException { - edit("state", "closed"); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getOwner() { + return owner; } /** - * Deletes this milestone. + * Gets creator. * + * @return the creator * @throws IOException * the io exception */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + public GHUser getCreator() throws IOException { + return root().intern(creator); } /** - * When was this milestone closed?. + * Gets due on. * - * @return the closed at + * @return the due on */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getClosedAt() { - return GitHubClient.parseInstant(closedAt); + public Date getDueOn() { + if (due_on == null) + return null; + return GitHubClient.parseDate(due_on); } /** - * Gets closed issues. + * When was this milestone closed?. * - * @return the closed issues + * @return the closed at + * @throws IOException + * the io exception */ - public int getClosedIssues() { - return closedIssues; + public Date getClosedAt() throws IOException { + return GitHubClient.parseDate(closed_at); } /** - * Gets creator. + * Gets title. * - * @return the creator + * @return the title */ - public GHUser getCreator() { - return root().intern(creator); + public String getTitle() { + return title; } /** @@ -92,22 +94,21 @@ public String getDescription() { } /** - * Gets due on. + * Gets closed issues. * - * @return the due on + * @return the closed issues */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getDueOn() { - return GitHubClient.parseInstant(dueOn); + public int getClosedIssues() { + return closed_issues; } /** - * Gets the html url. + * Gets open issues. * - * @return the html url + * @return the open issues */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public int getOpenIssues() { + return open_issues; } /** @@ -120,22 +121,12 @@ public int getNumber() { } /** - * Gets open issues. - * - * @return the open issues - */ - public int getOpenIssues() { - return openIssues; - } - - /** - * Gets owner. + * Gets the html url. * - * @return the owner + * @return the html url */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return owner; + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); } /** @@ -148,12 +139,13 @@ public GHMilestoneState getState() { } /** - * Gets title. + * Closes this milestone. * - * @return the title + * @throws IOException + * the io exception */ - public String getTitle() { - return title; + public void close() throws IOException { + edit("state", "closed"); } /** @@ -167,57 +159,53 @@ public void reopen() throws IOException { } /** - * Sets description. + * Deletes this milestone. * - * @param description - * the description * @throws IOException * the io exception */ - public void setDescription(String description) throws IOException { - edit("description", description); + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + } + + private void edit(String key, Object value) throws IOException { + root().createRequest().with(key, value).method("PATCH").withUrlPath(getApiRoute()).send(); } /** - * Sets due on. + * Sets title. * - * @param dueOn - * the due on + * @param title + * the title * @throws IOException * the io exception - * @deprecated Use {@link #setDueOn(Instant)} */ - @Deprecated - public void setDueOn(Date dueOn) throws IOException { - setDueOn(GitHubClient.toInstantOrNull(dueOn)); + public void setTitle(String title) throws IOException { + edit("title", title); } /** - * Sets due on. + * Sets description. * - * @param dueOn - * the due on + * @param description + * the description * @throws IOException * the io exception */ - public void setDueOn(Instant dueOn) throws IOException { - edit("due_on", GitHubClient.printInstant(dueOn)); + public void setDescription(String description) throws IOException { + edit("description", description); } /** - * Sets title. + * Sets due on. * - * @param title - * the title + * @param dueOn + * the due on * @throws IOException * the io exception */ - public void setTitle(String title) throws IOException { - edit("title", title); - } - - private void edit(String key, Object value) throws IOException { - root().createRequest().with(key, value).method("PATCH").withUrlPath(getApiRoute()).send(); + public void setDueOn(Date dueOn) throws IOException { + edit("due_on", GitHubClient.printDate(dueOn)); } /** diff --git a/src/main/java/org/kohsuke/github/GHMilestoneState.java b/src/main/java/org/kohsuke/github/GHMilestoneState.java index ab2030239d..85dcb9d5f4 100644 --- a/src/main/java/org/kohsuke/github/GHMilestoneState.java +++ b/src/main/java/org/kohsuke/github/GHMilestoneState.java @@ -8,8 +8,8 @@ */ public enum GHMilestoneState { - /** The closed. */ - CLOSED, /** The open. */ - OPEN + OPEN, + /** The closed. */ + CLOSED } diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index 05e52cd5ac..784f120b15 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -17,6 +17,12 @@ */ public class GHMyself extends GHUser { + /** + * Create default GHMyself instance + */ + public GHMyself() { + } + /** * Type of repositories returned during listing. */ @@ -25,92 +31,17 @@ public enum RepositoryListFilter { /** All public and private repositories that current user has access or collaborates to. */ ALL, - /** Public and private repositories that current user is a member. */ - MEMBER, - /** Public and private repositories owned by current user. */ OWNER, - /** Private repositories that current user has access or collaborates to. */ - PRIVATE, - /** Public repositories that current user has access or collaborates to. */ - PUBLIC; - } - - /** - * Create default GHMyself instance - */ - public GHMyself() { - } - - /** - * Add public SSH key for the user. - *

- * https://docs.github.com/en/rest/users/keys?apiVersion=2022-11-28#create-a-public-ssh-key-for-the-authenticated-user - * - * @param title - * Title of the SSH key - * @param key - * the public key - * @return the newly created Github key - * @throws IOException - * the io exception - */ - public GHKey addPublicKey(String title, String key) throws IOException { - return root().createRequest() - .withUrlPath("/user/keys") - .method("POST") - .with("title", title) - .with("key", key) - .fetch(GHKey.class); - } - - /** - * Gets the organization that this user belongs to. - * - * @return the all organizations - * @throws IOException - * the io exception - */ - public GHPersonSet getAllOrganizations() throws IOException { - GHPersonSet orgs = new GHPersonSet(); - Set names = new HashSet(); - for (GHOrganization o : root().createRequest() - .withUrlPath("/user/orgs") - .toIterable(GHOrganization[].class, null) - .toArray()) { - if (names.add(o.getLogin())) // in case of rumoured duplicates in the data - orgs.add(root().getOrganization(o.getLogin())); - } - return orgs; - } + PUBLIC, - /** - * Gets the all repositories this user owns (public and private). - * - * @return the all repositories - */ - public synchronized Map getAllRepositories() { - Map repositories = new TreeMap(); - for (GHRepository r : listRepositories()) { - repositories.put(r.getName(), r); - } - return Collections.unmodifiableMap(repositories); - } + /** Private repositories that current user has access or collaborates to. */ + PRIVATE, - /** - * Lists installations of your GitHub App that the authenticated user has explicit permission to access. You must - * use a user-to-server OAuth access token, created for a user who has authorized your GitHub App, to access this - * endpoint. - * - * @return the paged iterable - * @see List - * app installations accessible to the user access token - */ - public PagedIterable getAppInstallations() { - return new GHAppInstallationsIterable(root()); + /** Public and private repositories that current user is a member. */ + MEMBER; } /** @@ -143,19 +74,15 @@ public List getEmails2() throws IOException { } /** - * Gets your membership in a specific organization. + * Returns the read-only list of e-mail addresses configured for you. + *

+ * This corresponds to the stuff you configure in https://github.com/settings/emails, and not to be confused with + * {@link #getEmail()} that shows your public e-mail address set in https://github.com/settings/profile * - * @param o - * the o - * @return the membership - * @throws IOException - * the io exception + * @return Always non-null. */ - public GHMembership getMembership(GHOrganization o) throws IOException { - return root().createRequest() - .withUrlPath("/user/memberships/orgs/" + o.getLogin()) - .fetch(GHMembership.class) - .wrap(root()); + public PagedIterable listEmails() { + return root().createRequest().withUrlPath("/user/emails").toIterable(GHEmail[].class, null); } /** @@ -172,6 +99,28 @@ public List getPublicKeys() throws IOException { return root().createRequest().withUrlPath("/user/keys").toIterable(GHKey[].class, null).toList(); } + /** + * Add public SSH key for the user. + *

+ * https://docs.github.com/en/rest/users/keys?apiVersion=2022-11-28#create-a-public-ssh-key-for-the-authenticated-user + * + * @param title + * Title of the SSH key + * @param key + * the public key + * @return the newly created Github key + * @throws IOException + * the io exception + */ + public GHKey addPublicKey(String title, String key) throws IOException { + return root().createRequest() + .withUrlPath("/user/keys") + .method("POST") + .with("title", title) + .with("key", key) + .fetch(GHKey.class); + } + /** * Returns the read-only list of all the public verified keys of the current user. *

@@ -190,38 +139,38 @@ public List getPublicVerifiedKeys() throws IOException { } /** - * Returns the read-only list of e-mail addresses configured for you. - *

- * This corresponds to the stuff you configure in https://github.com/settings/emails, and not to be confused with - * {@link #getEmail()} that shows your public e-mail address set in https://github.com/settings/profile - * - * @return Always non-null. - */ - public PagedIterable listEmails() { - return root().createRequest().withUrlPath("/user/emails").toIterable(GHEmail[].class, null); - } - - /** - * List your organization memberships. + * Gets the organization that this user belongs to. * - * @return the paged iterable + * @return the all organizations + * @throws IOException + * the io exception */ - public PagedIterable listOrgMemberships() { - return listOrgMemberships(null); + public GHPersonSet getAllOrganizations() throws IOException { + GHPersonSet orgs = new GHPersonSet(); + Set names = new HashSet(); + for (GHOrganization o : root().createRequest() + .withUrlPath("/user/orgs") + .toIterable(GHOrganization[].class, null) + .toArray()) { + if (names.add(o.getLogin())) // in case of rumoured duplicates in the data + orgs.add(root().getOrganization(o.getLogin())); + } + return orgs; } /** - * List your organization memberships. + * Gets the all repositories this user owns (public and private). * - * @param state - * Filter by a specific state - * @return the paged iterable + * @return the all repositories + * @throws IOException + * the io exception */ - public PagedIterable listOrgMemberships(final GHMembership.State state) { - return root().createRequest() - .with("state", state) - .withUrlPath("/user/memberships/orgs") - .toIterable(GHMembership[].class, item -> item.wrap(root())); + public synchronized Map getAllRepositories() throws IOException { + Map repositories = new TreeMap(); + for (GHRepository r : listRepositories()) { + repositories.put(r.getName(), r); + } + return Collections.unmodifiableMap(repositories); } /** @@ -255,11 +204,6 @@ public PagedIterable listRepositories(final int pageSize) { return listRepositories(pageSize, RepositoryListFilter.ALL); } - // public void addEmails(Collection emails) throws IOException { - //// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails"); - // root.retrieveWithAuth3() - // } - /** * List repositories of a certain type that are accessible by current authenticated user using the specified page * size. @@ -277,4 +221,62 @@ public PagedIterable listRepositories(final int pageSize, final Re .toIterable(GHRepository[].class, null) .withPageSize(pageSize); } + + /** + * List your organization memberships. + * + * @return the paged iterable + */ + public PagedIterable listOrgMemberships() { + return listOrgMemberships(null); + } + + /** + * List your organization memberships. + * + * @param state + * Filter by a specific state + * @return the paged iterable + */ + public PagedIterable listOrgMemberships(final GHMembership.State state) { + return root().createRequest() + .with("state", state) + .withUrlPath("/user/memberships/orgs") + .toIterable(GHMembership[].class, item -> item.wrap(root())); + } + + /** + * Gets your membership in a specific organization. + * + * @param o + * the o + * @return the membership + * @throws IOException + * the io exception + */ + public GHMembership getMembership(GHOrganization o) throws IOException { + return root().createRequest() + .withUrlPath("/user/memberships/orgs/" + o.getLogin()) + .fetch(GHMembership.class) + .wrap(root()); + } + + // public void addEmails(Collection emails) throws IOException { + //// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails"); + // root.retrieveWithAuth3() + // } + + /** + * Lists installations of your GitHub App that the authenticated user has explicit permission to access. You must + * use a user-to-server OAuth access token, created for a user who has authorized your GitHub App, to access this + * endpoint. + * + * @return the paged iterable + * @see List + * app installations accessible to the user access token + */ + public PagedIterable getAppInstallations() { + return new GHAppInstallationsIterable(root()); + } } diff --git a/src/main/java/org/kohsuke/github/GHNotificationStream.java b/src/main/java/org/kohsuke/github/GHNotificationStream.java index 269ddf972f..7e62d7b6c6 100644 --- a/src/main/java/org/kohsuke/github/GHNotificationStream.java +++ b/src/main/java/org/kohsuke/github/GHNotificationStream.java @@ -1,7 +1,6 @@ package org.kohsuke.github; import java.io.IOException; -import java.time.Instant; import java.util.Date; import java.util.Iterator; import java.util.NoSuchElementException; @@ -26,13 +25,11 @@ * @see GHRepository#listNotifications() GHRepository#listNotifications() */ public class GHNotificationStream extends GitHubInteractiveObject implements Iterable { - private static final GHThread[] EMPTY_ARRAY = new GHThread[0]; private Boolean all, participating; + private String since; private String apiUrl; private boolean nonBlocking = false; - private String since; - /** * Instantiates a new GH notification stream. * @@ -46,6 +43,66 @@ public class GHNotificationStream extends GitHubInteractiveObject implements Ite this.apiUrl = apiUrl; } + /** + * Should the stream include notifications that are already read?. + * + * @param v + * the v + * @return the gh notification stream + */ + public GHNotificationStream read(boolean v) { + all = v; + return this; + } + + /** + * Should the stream be restricted to notifications in which the user is directly participating or mentioned?. + * + * @param v + * the v + * @return the gh notification stream + */ + public GHNotificationStream participating(boolean v) { + participating = v; + return this; + } + + /** + * Since gh notification stream. + * + * @param timestamp + * the timestamp + * @return the gh notification stream + */ + public GHNotificationStream since(long timestamp) { + return since(new Date(timestamp)); + } + + /** + * Since gh notification stream. + * + * @param dt + * the dt + * @return the gh notification stream + */ + public GHNotificationStream since(Date dt) { + since = GitHubClient.printDate(dt); + return this; + } + + /** + * If set to true, {@link #iterator()} will stop iterating instead of blocking and waiting for the updates to + * arrive. + * + * @param v + * the v + * @return the gh notification stream + */ + public GHNotificationStream nonBlocking(boolean v) { + this.nonBlocking = v; + return this; + } + /** * Returns an infinite blocking {@link Iterator} that returns {@link GHThread} as notifications arrive. * @@ -60,37 +117,31 @@ public Iterator iterator() { return new Iterator() { /** - * Next element in {@link #threads} to return. This counts down. + * Stuff we've fetched but haven't returned to the caller. Newer ones first. */ - private int idx = -1; + private GHThread[] threads = EMPTY_ARRAY; /** - * Next request should have "If-Modified-Since" header with this value. + * Next element in {@link #threads} to return. This counts down. */ - private String lastModified; + private int idx = -1; /** * threads whose updated_at is older than this should be ignored. */ private long lastUpdated = -1; - private GHThread next; - /** - * When is the next polling allowed? + * Next request should have "If-Modified-Since" header with this value. */ - private long nextCheckTime = -1; + private String lastModified; /** - * Stuff we've fetched but haven't returned to the caller. Newer ones first. + * When is the next polling allowed? */ - private GHThread[] threads = EMPTY_ARRAY; + private long nextCheckTime = -1; - public boolean hasNext() { - if (next == null) - next = fetch(); - return next != null; - } + private GHThread next; public GHThread next() { if (next == null) { @@ -104,12 +155,10 @@ public GHThread next() { return r; } - private long calcNextCheckTime(GitHubResponse response) { - String v = response.header("X-Poll-Interval"); - if (v == null) - v = "60"; - long seconds = Integer.parseInt(v); - return System.currentTimeMillis() + seconds * 1000; + public boolean hasNext() { + if (next == null) + next = fetch(); + return next != null; } GHThread fetch() { @@ -119,7 +168,7 @@ GHThread fetch() { // if we have fetched un-returned threads, use them first while (idx >= 0) { GHThread n = threads[idx--]; - long nt = n.getUpdatedAt().toEpochMilli(); + long nt = n.getUpdatedAt().getTime(); if (nt >= lastUpdated) { lastUpdated = nt; return n; @@ -138,9 +187,7 @@ GHThread fetch() { Thread.sleep(waitTime); } - if (lastModified != null) { - req.setHeader("If-Modified-Since", lastModified); - } + req.setHeader("If-Modified-Since", lastModified); Requester requester = req.withUrlPath(apiUrl); GitHubResponse response = ((GitHubPageContentsIterable) requester @@ -162,6 +209,14 @@ GHThread fetch() { throw new RuntimeException(e); } } + + private long calcNextCheckTime(GitHubResponse response) { + String v = response.header("X-Poll-Interval"); + if (v == null) + v = "60"; + long seconds = Integer.parseInt(v); + return System.currentTimeMillis() + seconds * 1000; + } }; } @@ -186,80 +241,9 @@ public void markAsRead() throws IOException { public void markAsRead(long timestamp) throws IOException { final Requester req = root().createRequest(); if (timestamp >= 0) - req.with("last_read_at", GitHubClient.printInstant(Instant.ofEpochMilli(timestamp))); + req.with("last_read_at", GitHubClient.printDate(new Date(timestamp))); req.withUrlPath(apiUrl).fetchHttpStatusCode(); } - /** - * If set to true, {@link #iterator()} will stop iterating instead of blocking and waiting for the updates to - * arrive. - * - * @param v - * the v - * @return the gh notification stream - */ - public GHNotificationStream nonBlocking(boolean v) { - this.nonBlocking = v; - return this; - } - - /** - * Should the stream be restricted to notifications in which the user is directly participating or mentioned?. - * - * @param v - * the v - * @return the gh notification stream - */ - public GHNotificationStream participating(boolean v) { - participating = v; - return this; - } - - /** - * Should the stream include notifications that are already read?. - * - * @param v - * the v - * @return the gh notification stream - */ - public GHNotificationStream read(boolean v) { - all = v; - return this; - } - - /** - * Since gh notification stream. - * - * @param dt - * the dt - * @return the gh notification stream - * @deprecated {@link #since(Instant)} - */ - @Deprecated - public GHNotificationStream since(Date dt) { - return since(GitHubClient.toInstantOrNull(dt)); - } - - /** - * Since gh notification stream. - * - * @param dt - * the dt - * @return the gh notification stream - */ - public GHNotificationStream since(Instant dt) { - since = GitHubClient.printInstant(dt); - return this; - } - - /** - * Since gh notification stream. - * - * @param timestamp - * the timestamp - * @return the gh notification stream - */ - public GHNotificationStream since(long timestamp) { - return since(new Date(timestamp)); - } + private static final GHThread[] EMPTY_ARRAY = new GHThread[0]; } diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 0545758887..9d9b2f4fe0 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -1,7 +1,6 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JacksonInject; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -10,7 +9,6 @@ import java.io.IOException; import java.lang.reflect.Field; import java.net.URL; -import java.time.Instant; import java.util.Date; import java.util.List; import java.util.Map; @@ -24,38 +22,17 @@ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") public abstract class GHObject extends GitHubInteractiveObject { - private static final ToStringStyle TOSTRING_STYLE = new ToStringStyle() { - { - this.setUseShortClassName(true); - } - - @Override - public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) { - // skip unimportant properties. '_' is a heuristics as important properties tend to have short names - if (fieldName.contains("_")) - return; - // avoid recursing other GHObject - if (value instanceof GHObject) - return; - // likewise no point in showing root - if (value instanceof GitHub) - return; - - super.append(buffer, fieldName, value, fullDetail); - } - }; + /** + * Capture response HTTP headers on the state object. + */ + protected transient Map> responseHeaderFields; - private String createdAt; + private String url; private long id; private String nodeId; + private String createdAt; private String updatedAt; - private String url; - - /** - * Capture response HTTP headers on the state object. - */ - protected transient Map> responseHeaderFields; /** * Instantiates a new GH object. @@ -64,34 +41,16 @@ public void append(StringBuffer buffer, String fieldName, Object value, Boolean } /** - * When was this resource created?. - * - * @return date created - * @throws IOException - * on error - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCreatedAt() throws IOException { - return GitHubClient.parseInstant(createdAt); - } - - /** - * Gets id. - * - * @return Unique ID number of this resource. - */ - public long getId() { - return id; - } - - /** - * Get Global node_id from Github object. + * Called by Jackson. * - * @return Global Node ID. - * @see Using Global Node IDs + * @param connectorResponse + * the {@link GitHubConnectorResponse} to get headers from. */ - public String getNodeId() { - return nodeId; + @JacksonInject + protected void setResponseHeaderFields(@CheckForNull GitHubConnectorResponse connectorResponse) { + if (connectorResponse != null) { + responseHeaderFields = connectorResponse.allHeaders(); + } } /** @@ -113,15 +72,14 @@ public Map> getResponseHeaderFields() { } /** - * When was this resource last updated?. + * When was this resource created?. * - * @return updated date + * @return date created * @throws IOException * on error */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getUpdatedAt() throws IOException { - return GitHubClient.parseInstant(updatedAt); + public Date getCreatedAt() throws IOException { + return GitHubClient.parseDate(createdAt); } /** @@ -133,6 +91,36 @@ public URL getUrl() { return GitHubClient.parseURL(url); } + /** + * When was this resource last updated?. + * + * @return updated date + * @throws IOException + * on error + */ + public Date getUpdatedAt() throws IOException { + return GitHubClient.parseDate(updatedAt); + } + + /** + * Get Global node_id from Github object. + * + * @return Global Node ID. + * @see Using Global Node IDs + */ + public String getNodeId() { + return nodeId; + } + + /** + * Gets id. + * + * @return Unique ID number of this resource. + */ + public long getId() { + return id; + } + /** * String representation to assist debugging and inspection. The output format of this string is not a committed * part of the API and is subject to change. @@ -149,16 +137,24 @@ protected boolean accept(Field field) { }.toString(); } - /** - * Called by Jackson. - * - * @param connectorResponse - * the {@link GitHubConnectorResponse} to get headers from. - */ - @JacksonInject - protected void setResponseHeaderFields(@CheckForNull GitHubConnectorResponse connectorResponse) { - if (connectorResponse != null) { - responseHeaderFields = connectorResponse.allHeaders(); + private static final ToStringStyle TOSTRING_STYLE = new ToStringStyle() { + { + this.setUseShortClassName(true); } - } + + @Override + public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) { + // skip unimportant properties. '_' is a heuristics as important properties tend to have short names + if (fieldName.contains("_")) + return; + // avoid recursing other GHObject + if (value instanceof GHObject) + return; + // likewise no point in showing root + if (value instanceof GitHub) + return; + + super.append(buffer, fieldName, value, fullDetail); + } + }; } diff --git a/src/main/java/org/kohsuke/github/GHOrgHook.java b/src/main/java/org/kohsuke/github/GHOrgHook.java index a483ec51ca..485e1c47a4 100644 --- a/src/main/java/org/kohsuke/github/GHOrgHook.java +++ b/src/main/java/org/kohsuke/github/GHOrgHook.java @@ -15,13 +15,15 @@ class GHOrgHook extends GHHook { transient GHOrganization organization; /** - * Gets the api route. + * Wrap. * - * @return the api route + * @param owner + * the owner + * @return the GH org hook */ - @Override - String getApiRoute() { - return String.format("/orgs/%s/hooks/%d", organization.getLogin(), getId()); + GHOrgHook wrap(GHOrganization owner) { + this.organization = owner; + return this; } /** @@ -35,14 +37,12 @@ GitHub root() { } /** - * Wrap. + * Gets the api route. * - * @param owner - * the owner - * @return the GH org hook + * @return the api route */ - GHOrgHook wrap(GHOrganization owner) { - this.organization = owner; - return this; + @Override + String getApiRoute() { + return String.format("/orgs/%s/hooks/%d", organization.getLogin(), getId()); } } diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index f86b990084..6d0e299330 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -18,252 +18,138 @@ */ public class GHOrganization extends GHPerson { - /** - * The enum Permission. - * - * @see RepositoryRole - */ - public enum Permission { - - /** The admin. */ - ADMIN, - /** The maintain. */ - MAINTAIN, - /** The pull. */ - PULL, - /** The push. */ - PUSH, - /** The triage. */ - TRIAGE, - /** Unknown, before we add the new permission to the enum */ - UNKNOWN - } - - /** - * Repository permissions (roles) for teams and collaborators. - */ - public static class RepositoryRole { - /** - * Custom. - * - * @param permission - * the permission - * @return the repository role - */ - public static RepositoryRole custom(String permission) { - return new RepositoryRole(permission); - } - - /** - * From. - * - * @param permission - * the permission - * @return the repository role - */ - public static RepositoryRole from(Permission permission) { - return custom(permission.toString().toLowerCase()); - } - - private final String permission; - - private RepositoryRole(String permission) { - this.permission = permission; - } - - /** - * To string. - * - * @return the string - */ - @Override - public String toString() { - return permission; - } - } - - /** - * Member's role in an organization. - */ - public enum Role { - - /** The admin. */ - ADMIN, - /** The user is an owner of the organization. */ - MEMBER /** The user is a non-owner member of the organization. */ - } - - private boolean hasOrganizationProjects; - /** * Create default GHOrganization instance */ public GHOrganization() { } - /** - * Adds (invites) a user to the organization. - * - * @param user - * the user - * @param role - * the role - * @throws IOException - * the io exception - * @see documentation - */ - public void add(GHUser user, Role role) throws IOException { - root().createRequest() - .method("PUT") - .with("role", role.name().toLowerCase()) - .withUrlPath("/orgs/" + login + "/memberships/" + user.getLogin()) - .send(); - } + private boolean has_organization_projects; /** - * Are projects enabled for organization boolean. + * Starts a builder that creates a new repository. + *

+ * You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()} to + * finally create a repository. * - * @return the boolean + * @param name + * the name + * @return the gh create repository builder */ - public boolean areOrganizationProjectsEnabled() { - return hasOrganizationProjects; + public GHCreateRepositoryBuilder createRepository(String name) { + return new GHCreateRepositoryBuilder(name, root(), "/orgs/" + login + "/repos"); } /** - * Conceals the membership. + * Teams by their names. * - * @param u - * the u + * @return the teams * @throws IOException * the io exception */ - public void conceal(GHUser u) throws IOException { - root().createRequest() - .method("DELETE") - .withUrlPath("/orgs/" + login + "/public_members/" + u.getLogin()) - .send(); + public Map getTeams() throws IOException { + Map r = new TreeMap(); + for (GHTeam t : listTeams()) { + r.put(t.getName(), t); + } + return r; } /** - * See https://api.github.com/hooks for possible names and their configuration scheme. TODO: produce type-safe - * binding + * List up all the teams. * - * @param name - * Type of the hook to be created. See https://api.github.com/hooks for possible names. - * @param config - * The configuration hash. - * @param events - * Can be null. Types of events to hook into. - * @param active - * the active - * @return the gh hook + * @return the paged iterable * @throws IOException * the io exception */ - public GHHook createHook(String name, Map config, Collection events, boolean active) - throws IOException { - return GHHooks.orgContext(this).createHook(name, config, events, active); + public PagedIterable listTeams() throws IOException { + return root().createRequest() + .withUrlPath(String.format("/orgs/%s/teams", login)) + .toIterable(GHTeam[].class, item -> item.wrapUp(this)); } /** - * Creates a project for the organization. + * Gets a single team by ID. * - * @param name - * the name - * @param body - * the body - * @return the gh project + * @param teamId + * id of the team that we want to query for + * @return the team * @throws IOException * the io exception + * @see documentation */ - public GHProject createProject(String name, String body) throws IOException { + public GHTeam getTeam(long teamId) throws IOException { return root().createRequest() - .method("POST") - .with("name", name) - .with("body", body) - .withUrlPath(String.format("/orgs/%s/projects", login)) - .fetch(GHProject.class); - } - - /** - * Starts a builder that creates a new repository. - *

- * You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()} to - * finally create a repository. - * - * @param name - * the name - * @return the gh create repository builder - */ - public GHCreateRepositoryBuilder createRepository(String name) { - return new GHCreateRepositoryBuilder(name, root(), "/orgs/" + login + "/repos"); + .withUrlPath(String.format("/organizations/%d/team/%d", getId(), teamId)) + .fetch(GHTeam.class) + .wrapUp(this); } /** - * Starts a builder that creates a new team. - *

- * You use the returned builder to set various properties, then call {@link GHTeamBuilder#create()} to finally - * create a team. + * Finds a team that has the given name in its {@link GHTeam#getName()}. * * @param name * the name - * @return the gh create repository builder - */ - public GHTeamBuilder createTeam(String name) { - return new GHTeamBuilder(root(), login, name); - } - - /** - * Create web hook gh hook. - * - * @param url - * the url - * @return the gh hook + * @return the team by name * @throws IOException * the io exception */ - public GHHook createWebHook(URL url) throws IOException { - return createWebHook(url, null); + public GHTeam getTeamByName(String name) throws IOException { + for (GHTeam t : listTeams()) { + if (t.getName().equals(name)) + return t; + } + return null; } /** - * Create web hook gh hook. + * Finds a team that has the given slug in its {@link GHTeam#getSlug()}. * - * @param url - * the url - * @param events - * the events - * @return the gh hook + * @param slug + * the slug + * @return the team by slug * @throws IOException * the io exception + * @see documentation */ - public GHHook createWebHook(URL url, Collection events) throws IOException { - return createHook("web", Collections.singletonMap("url", url.toExternalForm()), events, true); + public GHTeam getTeamBySlug(String slug) throws IOException { + return root().createRequest() + .withUrlPath(String.format("/orgs/%s/teams/%s", login, slug)) + .fetch(GHTeam.class) + .wrapUp(this); } /** - * Deletes hook. + * List up all the external groups. * - * @param id - * the id + * @return the paged iterable * @throws IOException * the io exception + * @see documentation */ - public void deleteHook(int id) throws IOException { - GHHooks.orgContext(this).deleteHook(id); + public PagedIterable listExternalGroups() throws IOException { + return listExternalGroups(null); } /** - * Sets organization projects enabled status boolean. + * List up all the external groups with a given text in their name * - * @param newStatus - * enable status + * @param displayName + * the text that must be part of the returned groups name + * @return the paged iterable * @throws IOException * the io exception + * @see documentation */ - public void enableOrganizationProjects(boolean newStatus) throws IOException { - edit("has_organization_projects", newStatus); + public PagedIterable listExternalGroups(final String displayName) throws IOException { + final Requester requester = root().createRequest() + .withUrlPath(String.format("/orgs/%s/external-groups", login)); + if (displayName != null) { + requester.with("display_name", displayName); + } + return new GHExternalGroupIterable(this, requester); } /** @@ -291,27 +177,50 @@ public GHExternalGroup getExternalGroup(final long groupId) throws IOException { } /** - * Gets hook. - * - * @param id - * the id - * @return the hook - * @throws IOException - * the io exception + * Member's role in an organization. */ - public GHHook getHook(int id) throws IOException { - return GHHooks.orgContext(this).getHook(id); + public enum Role { + + /** The admin. */ + ADMIN, + /** The user is an owner of the organization. */ + MEMBER /** The user is a non-owner member of the organization. */ } /** - * Retrieves the currently configured hooks. + * Adds (invites) a user to the organization. * - * @return the hooks + * @param user + * the user + * @param role + * the role * @throws IOException * the io exception + * @see documentation */ - public List getHooks() throws IOException { - return GHHooks.orgContext(this).getHooks(); + public void add(GHUser user, Role role) throws IOException { + root().createRequest() + .method("PUT") + .with("role", role.name().toLowerCase()) + .withUrlPath("/orgs/" + login + "/memberships/" + user.getLogin()) + .send(); + } + + /** + * Checks if this organization has the specified user as a member. + * + * @param user + * the user + * @return the boolean + */ + public boolean hasMember(GHUser user) { + try { + root().createRequest().withUrlPath("/orgs/" + login + "/members/" + user.getLogin()).send(); + return true; + } catch (IOException ignore) { + return false; + } } /** @@ -335,258 +244,360 @@ public GHMembership getMembership(String username) throws IOException { } /** - * Gets all the open pull requests in this organization. + * Remove a member of the organisation - which will remove them from all teams, and remove their access to the + * organization’s repositories. * - * @return the pull requests + * @param user + * the user * @throws IOException * the io exception */ - public List getPullRequests() throws IOException { - List all = new ArrayList(); - for (GHRepository r : getRepositoriesWithOpenPullRequests()) { - all.addAll(r.queryPullRequests().state(GHIssueState.OPEN).list().toList()); + public void remove(GHUser user) throws IOException { + root().createRequest().method("DELETE").withUrlPath("/orgs/" + login + "/members/" + user.getLogin()).send(); + } + + /** + * Checks if this organization has the specified user as a public member. + * + * @param user + * the user + * @return the boolean + */ + public boolean hasPublicMember(GHUser user) { + try { + root().createRequest().withUrlPath("/orgs/" + login + "/public_members/" + user.getLogin()).send(); + return true; + } catch (IOException ignore) { + return false; } - return all; } /** - * List repositories that has some open pull requests. - *

- * This used to be an efficient method that didn't involve traversing every repository, but now it doesn't do any - * optimization. + * Publicizes the membership. * - * @return the repositories with open pull requests + * @param u + * the u * @throws IOException * the io exception */ - public List getRepositoriesWithOpenPullRequests() throws IOException { - List r = new ArrayList(); - for (GHRepository repository : listRepositories().withPageSize(100)) { - List pullRequests = repository.queryPullRequests().state(GHIssueState.OPEN).list().toList(); - if (pullRequests.size() > 0) { - r.add(repository); - } - } - return r; + public void publicize(GHUser u) throws IOException { + root().createRequest().method("PUT").withUrlPath("/orgs/" + login + "/public_members/" + u.getLogin()).send(); } /** - * Gets a single team by ID. + * All the members of this organization. * - * @param teamId - * id of the team that we want to query for - * @return the team + * @return the paged iterable * @throws IOException * the io exception - * @see documentation */ - public GHTeam getTeam(long teamId) throws IOException { - return root().createRequest() - .withUrlPath(String.format("/organizations/%d/team/%d", getId(), teamId)) - .fetch(GHTeam.class) - .wrapUp(this); + public PagedIterable listMembers() throws IOException { + return listMembers("members"); } /** - * Finds a team that has the given name in its {@link GHTeam#getName()}. + * All the public members of this organization. * - * @param name - * the name - * @return the team by name + * @return the paged iterable + * @throws IOException + * the io exception */ - public GHTeam getTeamByName(String name) { - for (GHTeam t : listTeams()) { - if (t.getName().equals(name)) - return t; - } - return null; + public PagedIterable listPublicMembers() throws IOException { + return listMembers("public_members"); } /** - * Finds a team that has the given slug in its {@link GHTeam#getSlug()}. + * All the outside collaborators of this organization. * - * @param slug - * the slug - * @return the team by slug + * @return the paged iterable * @throws IOException * the io exception - * @see documentation */ - public GHTeam getTeamBySlug(String slug) throws IOException { - return root().createRequest() - .withUrlPath(String.format("/orgs/%s/teams/%s", login, slug)) - .fetch(GHTeam.class) - .wrapUp(this); + public PagedIterable listOutsideCollaborators() throws IOException { + return listMembers("outside_collaborators"); + } + + private PagedIterable listMembers(String suffix) throws IOException { + return listMembers(suffix, null, null); } /** - * Teams by their names. + * List members with filter paged iterable. * - * @return the teams + * @param filter + * the filter + * @return the paged iterable + * @throws IOException + * the io exception */ - public Map getTeams() { - Map r = new TreeMap(); - for (GHTeam t : listTeams()) { - r.put(t.getName(), t); - } - return r; + public PagedIterable listMembersWithFilter(String filter) throws IOException { + return listMembers("members", filter, null); } /** - * Checks if this organization has the specified user as a member. + * List outside collaborators with filter paged iterable. * - * @param user - * the user - * @return the boolean + * @param filter + * the filter + * @return the paged iterable + * @throws IOException + * the io exception */ - public boolean hasMember(GHUser user) { - try { - root().createRequest().withUrlPath("/orgs/" + login + "/members/" + user.getLogin()).send(); - return true; - } catch (IOException ignore) { - return false; - } + public PagedIterable listOutsideCollaboratorsWithFilter(String filter) throws IOException { + return listMembers("outside_collaborators", filter, null); } /** - * Checks if this organization has the specified user as a public member. + * List members with specified role paged iterable. * - * @param user - * the user - * @return the boolean + * @param role + * the role + * @return the paged iterable + * @throws IOException + * the io exception */ - public boolean hasPublicMember(GHUser user) { - try { - root().createRequest().withUrlPath("/orgs/" + login + "/public_members/" + user.getLogin()).send(); - return true; - } catch (IOException ignore) { - return false; - } + public PagedIterable listMembersWithRole(String role) throws IOException { + return listMembers("members", null, role); + } + + private PagedIterable listMembers(final String suffix, final String filter, String role) + throws IOException { + return root().createRequest() + .withUrlPath(String.format("/orgs/%s/%s", login, suffix)) + .with("filter", filter) + .with("role", role) + .toIterable(GHUser[].class, null); } /** - * Lists events performed by a user (this includes private events if the caller is authenticated. + * List up all the security managers. * * @return the paged iterable * @throws IOException - * Signals that an I/O exception has occurred. + * the io exception */ - public PagedIterable listEvents() throws IOException { + public PagedIterable listSecurityManagers() throws IOException { return root().createRequest() - .withUrlPath(String.format("/orgs/%s/events", login)) - .toIterable(GHEventInfo[].class, null); + .withUrlPath(String.format("/orgs/%s/security-managers", login)) + .toIterable(GHTeam[].class, item -> item.wrapUp(this)); } /** - * List up all the external groups. + * Conceals the membership. * - * @return the paged iterable - * @see documentation + * @param u + * the u + * @throws IOException + * the io exception */ - public PagedIterable listExternalGroups() { - return listExternalGroups(null); + public void conceal(GHUser u) throws IOException { + root().createRequest() + .method("DELETE") + .withUrlPath("/orgs/" + login + "/public_members/" + u.getLogin()) + .send(); } /** - * List up all the external groups with a given text in their name + * Are projects enabled for organization boolean. * - * @param displayName - * the text that must be part of the returned groups name - * @return the paged iterable - * @see documentation + * @return the boolean */ - public PagedIterable listExternalGroups(final String displayName) { - final Requester requester = root().createRequest() - .withUrlPath(String.format("/orgs/%s/external-groups", login)); - if (displayName != null) { - requester.with("display_name", displayName); - } - return new GHExternalGroupIterable(this, requester); + public boolean areOrganizationProjectsEnabled() { + return has_organization_projects; } /** - * All the members of this organization. + * Sets organization projects enabled status boolean. * - * @return the paged iterable + * @param newStatus + * enable status + * @throws IOException + * the io exception */ - public PagedIterable listMembers() { - return listMembers("members"); + public void enableOrganizationProjects(boolean newStatus) throws IOException { + edit("has_organization_projects", newStatus); + } + + private void edit(String key, Object value) throws IOException { + root().createRequest() + .withUrlPath(String.format("/orgs/%s", login)) + .method("PATCH") + .with(key, value) + .fetchInto(this); } /** - * List members with filter paged iterable. + * Returns the projects for this organization. * - * @param filter - * the filter + * @param status + * The status filter (all, open or closed). * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listMembersWithFilter(String filter) { - return listMembers("members", filter, null); + public PagedIterable listProjects(final GHProject.ProjectStateFilter status) throws IOException { + return root().createRequest() + .with("state", status) + .withUrlPath(String.format("/orgs/%s/projects", login)) + .toIterable(GHProject[].class, null); } /** - * List members with specified role paged iterable. + * Returns all open projects for the organization. * - * @param role - * the role * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listMembersWithRole(String role) { - return listMembers("members", null, role); + public PagedIterable listProjects() throws IOException { + return listProjects(GHProject.ProjectStateFilter.OPEN); } /** - * All the outside collaborators of this organization. + * Creates a project for the organization. * - * @return the paged iterable + * @param name + * the name + * @param body + * the body + * @return the gh project + * @throws IOException + * the io exception */ - public PagedIterable listOutsideCollaborators() { - return listMembers("outside_collaborators"); + public GHProject createProject(String name, String body) throws IOException { + return root().createRequest() + .method("POST") + .with("name", name) + .with("body", body) + .withUrlPath(String.format("/orgs/%s/projects", login)) + .fetch(GHProject.class); } /** - * List outside collaborators with filter paged iterable. + * The enum Permission. * - * @param filter - * the filter - * @return the paged iterable + * @see RepositoryRole */ - public PagedIterable listOutsideCollaboratorsWithFilter(String filter) { - return listMembers("outside_collaborators", filter, null); + public enum Permission { + + /** The admin. */ + ADMIN, + /** The maintain. */ + MAINTAIN, + /** The push. */ + PUSH, + /** The triage. */ + TRIAGE, + /** The pull. */ + PULL, + /** Unknown, before we add the new permission to the enum */ + UNKNOWN } /** - * Returns all open projects for the organization. + * Repository permissions (roles) for teams and collaborators. + */ + public static class RepositoryRole { + private final String permission; + + private RepositoryRole(String permission) { + this.permission = permission; + } + + /** + * Custom. + * + * @param permission + * the permission + * @return the repository role + */ + public static RepositoryRole custom(String permission) { + return new RepositoryRole(permission); + } + + /** + * From. + * + * @param permission + * the permission + * @return the repository role + */ + public static RepositoryRole from(Permission permission) { + return custom(permission.toString().toLowerCase()); + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + return permission; + } + } + + /** + * Starts a builder that creates a new team. + *

+ * You use the returned builder to set various properties, then call {@link GHTeamBuilder#create()} to finally + * create a team. * - * @return the paged iterable + * @param name + * the name + * @return the gh create repository builder */ - public PagedIterable listProjects() { - return listProjects(GHProject.ProjectStateFilter.OPEN); + public GHTeamBuilder createTeam(String name) { + return new GHTeamBuilder(root(), login, name); } /** - * Returns the projects for this organization. + * List repositories that has some open pull requests. + *

+ * This used to be an efficient method that didn't involve traversing every repository, but now it doesn't do any + * optimization. * - * @param status - * The status filter (all, open or closed). - * @return the paged iterable + * @return the repositories with open pull requests + * @throws IOException + * the io exception */ - public PagedIterable listProjects(final GHProject.ProjectStateFilter status) { - return root().createRequest() - .with("state", status) - .withUrlPath(String.format("/orgs/%s/projects", login)) - .toIterable(GHProject[].class, null); + public List getRepositoriesWithOpenPullRequests() throws IOException { + List r = new ArrayList(); + for (GHRepository repository : listRepositories().withPageSize(100)) { + List pullRequests = repository.queryPullRequests().state(GHIssueState.OPEN).list().toList(); + if (pullRequests.size() > 0) { + r.add(repository); + } + } + return r; } /** - * All the public members of this organization. + * Gets all the open pull requests in this organization. + * + * @return the pull requests + * @throws IOException + * the io exception + */ + public List getPullRequests() throws IOException { + List all = new ArrayList(); + for (GHRepository r : getRepositoriesWithOpenPullRequests()) { + all.addAll(r.queryPullRequests().state(GHIssueState.OPEN).list().toList()); + } + return all; + } + + /** + * Lists events performed by a user (this includes private events if the caller is authenticated. * * @return the paged iterable + * @throws IOException + * Signals that an I/O exception has occurred. */ - public PagedIterable listPublicMembers() { - return listMembers("public_members"); + public PagedIterable listEvents() throws IOException { + return root().createRequest() + .withUrlPath(String.format("/orgs/%s/events", login)) + .toIterable(GHEventInfo[].class, null); } /** @@ -603,69 +614,87 @@ public PagedIterable listRepositories() { } /** - * List up all the security managers. + * Retrieves the currently configured hooks. * - * @return the paged iterable + * @return the hooks + * @throws IOException + * the io exception */ - public PagedIterable listSecurityManagers() { - return root().createRequest() - .withUrlPath(String.format("/orgs/%s/security-managers", login)) - .toIterable(GHTeam[].class, item -> item.wrapUp(this)); + public List getHooks() throws IOException { + return GHHooks.orgContext(this).getHooks(); } /** - * List up all the teams. + * Gets hook. * - * @return the paged iterable + * @param id + * the id + * @return the hook + * @throws IOException + * the io exception */ - public PagedIterable listTeams() { - return root().createRequest() - .withUrlPath(String.format("/orgs/%s/teams", login)) - .toIterable(GHTeam[].class, item -> item.wrapUp(this)); + public GHHook getHook(int id) throws IOException { + return GHHooks.orgContext(this).getHook(id); } /** - * Publicizes the membership. + * Deletes hook. * - * @param u - * the u + * @param id + * the id * @throws IOException * the io exception */ - public void publicize(GHUser u) throws IOException { - root().createRequest().method("PUT").withUrlPath("/orgs/" + login + "/public_members/" + u.getLogin()).send(); + public void deleteHook(int id) throws IOException { + GHHooks.orgContext(this).deleteHook(id); } /** - * Remove a member of the organisation - which will remove them from all teams, and remove their access to the - * organization’s repositories. + * See https://api.github.com/hooks for possible names and their configuration scheme. TODO: produce type-safe + * binding * - * @param user - * the user + * @param name + * Type of the hook to be created. See https://api.github.com/hooks for possible names. + * @param config + * The configuration hash. + * @param events + * Can be null. Types of events to hook into. + * @param active + * the active + * @return the gh hook * @throws IOException * the io exception */ - public void remove(GHUser user) throws IOException { - root().createRequest().method("DELETE").withUrlPath("/orgs/" + login + "/members/" + user.getLogin()).send(); - } - - private void edit(String key, Object value) throws IOException { - root().createRequest() - .withUrlPath(String.format("/orgs/%s", login)) - .method("PATCH") - .with(key, value) - .fetchInto(this); + public GHHook createHook(String name, Map config, Collection events, boolean active) + throws IOException { + return GHHooks.orgContext(this).createHook(name, config, events, active); } - private PagedIterable listMembers(String suffix) { - return listMembers(suffix, null, null); + /** + * Create web hook gh hook. + * + * @param url + * the url + * @param events + * the events + * @return the gh hook + * @throws IOException + * the io exception + */ + public GHHook createWebHook(URL url, Collection events) throws IOException { + return createHook("web", Collections.singletonMap("url", url.toExternalForm()), events, true); } - private PagedIterable listMembers(final String suffix, final String filter, String role) { - return root().createRequest() - .withUrlPath(String.format("/orgs/%s/%s", login, suffix)) - .with("filter", filter) - .with("role", role) - .toIterable(GHUser[].class, null); + /** + * Create web hook gh hook. + * + * @param url + * the url + * @return the gh hook + * @throws IOException + * the io exception + */ + public GHHook createWebHook(URL url) throws IOException { + return createWebHook(url, null); } } diff --git a/src/main/java/org/kohsuke/github/GHPermissionType.java b/src/main/java/org/kohsuke/github/GHPermissionType.java index 2efd179a18..8dc9ca1a14 100644 --- a/src/main/java/org/kohsuke/github/GHPermissionType.java +++ b/src/main/java/org/kohsuke/github/GHPermissionType.java @@ -10,14 +10,14 @@ public enum GHPermissionType { /** The admin. */ ADMIN(30), - /** The none. */ - NONE(0), + /** The write. */ + WRITE(20), /** The read. */ READ(10), + /** The none. */ + NONE(0), /** The unknown permission type returned when an unrecognized permission type is returned. */ - UNKNOWN(-5), - /** The write. */ - WRITE(20); + UNKNOWN(-5); private final int level; diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index 52c0557e4e..175883b3b3 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -1,11 +1,8 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; - import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Collections; import java.util.Date; import java.util.Map; @@ -20,122 +17,166 @@ */ public abstract class GHPerson extends GHObject { - /** The public gists. */ - protected int followers, following, publicRepos, publicGists; + /** + * Create default GHPerson instance + */ + public GHPerson() { + } - /** The html url. */ - protected String htmlUrl; + /** The avatar url. */ + // core data fields that exist even for "small" user data (such as the user info in pull request) + protected String login, avatar_url; /** The twitter username. */ // other fields (that only show up in full data) - protected String location, blog, email, bio, name, company, type, twitterUsername; + protected String location, blog, email, bio, name, company, type, twitter_username; - /** The avatar url. */ - // core data fields that exist even for "small" user data (such as the user info in pull request) - protected String login, avatarUrl; + /** The html url. */ + protected String html_url; + + /** The public gists. */ + protected int followers, following, public_repos, public_gists; /** The hireable. */ - protected boolean siteAdmin, hireable; + protected boolean site_admin, hireable; /** The total private repos. */ // other fields (that only show up in full data) that require privileged scope - protected Integer totalPrivateRepos; + protected Integer total_private_repos; /** - * Create default GHPerson instance + * Fully populate the data by retrieving missing data. + *

+ * Depending on the original API call where this object is created, it may not contain everything. + * + * @throws IOException + * the io exception */ - public GHPerson() { + protected synchronized void populate() throws IOException { + if (super.getCreatedAt() != null) { + return; // already populated + } + if (isOffline()) { + return; // cannot populate, will have to live with what we have + } + URL url = getUrl(); + if (url != null) { + root().createRequest().setRawUrlPath(url.toString()).fetchInto(this); + } } /** - * Returns a string of the avatar image URL. + * Gets the public repositories this user owns. * - * @return the avatar url + *

+ * To list your own repositories, including private repositories, use {@link GHMyself#listRepositories()} + * + * @return the repositories + * @throws IOException + * the io exception */ - public String getAvatarUrl() { - return avatarUrl; + public synchronized Map getRepositories() throws IOException { + Map repositories = new TreeMap(); + for (GHRepository r : listRepositories().withPageSize(100)) { + repositories.put(r.getName(), r); + } + return Collections.unmodifiableMap(repositories); } /** - * Gets the blog URL of this user. + * List all the repositories using a default of 30 items page size. + *

+ * Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned. * - * @return the blog - * @throws IOException - * the io exception + * @return the paged iterable */ - public String getBlog() throws IOException { - populate(); - return blog; + public PagedIterable listRepositories() { + return root().createRequest() + .withUrlPath("/users/" + login + "/repos") + .toIterable(GHRepository[].class, null) + .withPageSize(30); } /** - * Gets the company name of this user, like "Sun Microsystems, Inc." + * Lists up all the repositories using the specified page size. * - * @return the company - * @throws IOException - * the io exception + * @param pageSize + * size for each page of items returned by GitHub. Maximum page size is 100. Unlike + * {@link #getRepositories()}, this does not wait until all the repositories are returned. + * @return the paged iterable + * @deprecated Use #listRepositories().withPageSize() instead. */ - public String getCompany() throws IOException { - populate(); - return company; + @Deprecated + public PagedIterable listRepositories(final int pageSize) { + return listRepositories().withPageSize(pageSize); } /** - * Gets the created at. + * Gets repository. * - * @return the created at + * @param name + * the name + * @return null if the repository was not found * @throws IOException - * Signals that an I/O exception has occurred. + * the io exception */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCreatedAt() throws IOException { - populate(); - return super.getCreatedAt(); + public GHRepository getRepository(String name) throws IOException { + try { + return GHRepository.read(root(), login, name); + } catch (FileNotFoundException e) { + return null; + } } /** - * Gets the e-mail address of the user. + * Lists events for an organization or an user. * - * @return the email + * @return the paged iterable * @throws IOException * the io exception */ - public String getEmail() throws IOException { - populate(); - return email; + public abstract PagedIterable listEvents() throws IOException; + + /** + * Returns a string of the avatar image URL. + * + * @return the avatar url + */ + public String getAvatarUrl() { + return avatar_url; } /** - * Gets followers count. + * Gets the login ID of this user, like 'kohsuke'. * - * @return the followers count - * @throws IOException - * the io exception + * @return the login */ - public int getFollowersCount() throws IOException { - populate(); - return followers; + public String getLogin() { + return login; } /** - * Gets following count. + * Gets the human-readable name of the user, like "Kohsuke Kawaguchi". * - * @return the following count + * @return the name * @throws IOException * the io exception */ - public int getFollowingCount() throws IOException { + public String getName() throws IOException { populate(); - return following; + return name; } /** - * Gets the html url. + * Gets the company name of this user, like "Sun Microsystems, Inc." * - * @return the html url + * @return the company + * @throws IOException + * the io exception */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public String getCompany() throws IOException { + populate(); + return company; } /** @@ -151,201 +192,155 @@ public String getLocation() throws IOException { } /** - * Gets the login ID of this user, like 'kohsuke'. + * Gets the Twitter Username of this user, like "GitHub". * - * @return the login + * @return the Twitter username + * @throws IOException + * the io exception */ - public String getLogin() { - return login; + public String getTwitterUsername() throws IOException { + populate(); + return twitter_username; } /** - * Gets the human-readable name of the user, like "Kohsuke Kawaguchi". + * Gets the created at. * - * @return the name + * @return the created at * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public String getName() throws IOException { + public Date getCreatedAt() throws IOException { populate(); - return name; + return super.getCreatedAt(); } /** - * Gets public gist count. + * Gets the updated at. * - * @return the public gist count + * @return the updated at * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public int getPublicGistCount() throws IOException { + public Date getUpdatedAt() throws IOException { populate(); - return publicGists; + return super.getUpdatedAt(); } /** - * Gets public repo count. + * Gets the blog URL of this user. * - * @return the public repo count + * @return the blog * @throws IOException * the io exception */ - public int getPublicRepoCount() throws IOException { + public String getBlog() throws IOException { populate(); - return publicRepos; + return blog; } /** - * Gets the public repositories this user owns. - * - *

- * To list your own repositories, including private repositories, use {@link GHMyself#listRepositories()} + * Gets the html url. * - * @return the repositories + * @return the html url */ - public synchronized Map getRepositories() { - Map repositories = new TreeMap(); - for (GHRepository r : listRepositories().withPageSize(100)) { - repositories.put(r.getName(), r); - } - return Collections.unmodifiableMap(repositories); + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); } /** - * Gets repository. + * Gets the e-mail address of the user. * - * @param name - * the name - * @return null if the repository was not found + * @return the email * @throws IOException * the io exception */ - public GHRepository getRepository(String name) throws IOException { - try { - return GHRepository.read(root(), login, name); - } catch (FileNotFoundException e) { - return null; - } + public String getEmail() throws IOException { + populate(); + return email; } /** - * Gets total private repo count. + * Gets public gist count. * - * @return the total private repo count + * @return the public gist count * @throws IOException * the io exception */ - public Optional getTotalPrivateRepoCount() throws IOException { + public int getPublicGistCount() throws IOException { populate(); - return Optional.ofNullable(totalPrivateRepos); + return public_gists; } /** - * Gets the Twitter Username of this user, like "GitHub". + * Gets public repo count. * - * @return the Twitter username + * @return the public repo count * @throws IOException * the io exception */ - public String getTwitterUsername() throws IOException { + public int getPublicRepoCount() throws IOException { populate(); - return twitterUsername; + return public_repos; } /** - * Gets the type. This is either "User" or "Organization". + * Gets following count. * - * @return the type + * @return the following count * @throws IOException * the io exception */ - public String getType() throws IOException { - if (type == null) { - populate(); - } - return type; + public int getFollowingCount() throws IOException { + populate(); + return following; } /** - * Gets the updated at. + * Gets followers count. * - * @return the updated at + * @return the followers count * @throws IOException - * Signals that an I/O exception has occurred. + * the io exception */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getUpdatedAt() throws IOException { + public int getFollowersCount() throws IOException { populate(); - return super.getUpdatedAt(); + return followers; } /** - * Gets the siteAdmin field. + * Gets the type. This is either "User" or "Organization". * - * @return the siteAdmin field + * @return the type * @throws IOException * the io exception */ - public boolean isSiteAdmin() throws IOException { + public String getType() throws IOException { populate(); - return siteAdmin; + return type; } /** - * Lists events for an organization or an user. + * Gets the site_admin field. * - * @return the paged iterable + * @return the site_admin field * @throws IOException * the io exception */ - public abstract PagedIterable listEvents() throws IOException; - - /** - * List all the repositories using a default of 30 items page size. - *

- * Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned. - * - * @return the paged iterable - */ - public PagedIterable listRepositories() { - return root().createRequest() - .withUrlPath("/users/" + login + "/repos") - .toIterable(GHRepository[].class, null) - .withPageSize(30); - } - - /** - * Lists up all the repositories using the specified page size. - * - * @param pageSize - * size for each page of items returned by GitHub. Maximum page size is 100. Unlike - * {@link #getRepositories()}, this does not wait until all the repositories are returned. - * @return the paged iterable - * @deprecated Use #listRepositories().withPageSize() instead. - */ - @Deprecated - public PagedIterable listRepositories(final int pageSize) { - return listRepositories().withPageSize(pageSize); + public boolean isSiteAdmin() throws IOException { + populate(); + return site_admin; } /** - * Fully populate the data by retrieving missing data. - *

- * Depending on the original API call where this object is created, it may not contain everything. + * Gets total private repo count. * + * @return the total private repo count * @throws IOException * the io exception */ - protected synchronized void populate() throws IOException { - if (super.getCreatedAt() != null) { - return; // already populated - } - if (isOffline()) { - return; // cannot populate, will have to live with what we have - } - URL url = getUrl(); - if (url != null) { - root().createRequest().setRawUrlPath(url.toString()).fetchInto(this); - } + public Optional getTotalPrivateRepoCount() throws IOException { + populate(); + return Optional.ofNullable(total_private_repos); } } diff --git a/src/main/java/org/kohsuke/github/GHPersonSet.java b/src/main/java/org/kohsuke/github/GHPersonSet.java index cd1bf9788e..c737249b5e 100644 --- a/src/main/java/org/kohsuke/github/GHPersonSet.java +++ b/src/main/java/org/kohsuke/github/GHPersonSet.java @@ -46,9 +46,11 @@ public GHPersonSet(T... c) { * * @param initialCapacity * the initial capacity + * @param loadFactor + * the load factor */ - public GHPersonSet(int initialCapacity) { - super(initialCapacity); + public GHPersonSet(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); } /** @@ -56,11 +58,9 @@ public GHPersonSet(int initialCapacity) { * * @param initialCapacity * the initial capacity - * @param loadFactor - * the load factor */ - public GHPersonSet(int initialCapacity, float loadFactor) { - super(initialCapacity, loadFactor); + public GHPersonSet(int initialCapacity) { + super(initialCapacity); } /** diff --git a/src/main/java/org/kohsuke/github/GHProject.java b/src/main/java/org/kohsuke/github/GHProject.java index 7243833ec5..3d0ebdd489 100644 --- a/src/main/java/org/kohsuke/github/GHProject.java +++ b/src/main/java/org/kohsuke/github/GHProject.java @@ -40,174 +40,149 @@ public class GHProject extends GHObject { /** - * The enum ProjectState. + * Create default GHProject instance */ - public enum ProjectState { - - /** The closed. */ - CLOSED, - /** The open. */ - OPEN + public GHProject() { } - /** - * The enum ProjectStateFilter. - */ - public static enum ProjectStateFilter { - - /** The all. */ - ALL, - /** The closed. */ - CLOSED, - /** The open. */ - OPEN - } + /** The owner. */ + protected GHObject owner; - private String body; - private GHUser creator; - private String htmlUrl; + private String owner_url; + private String html_url; private String name; + private String body; private int number; - private String ownerUrl; private String state; - - /** The owner. */ - protected GHObject owner; - - /** - * Create default GHProject instance - */ - public GHProject() { - } + private GHUser creator; /** - * Create column gh project column. + * Gets the html url. * - * @param name - * the name - * @return the gh project column + * @return the html url * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public GHProjectColumn createColumn(String name) throws IOException { - return root().createRequest() - .method("POST") - .with("name", name) - .withUrlPath(String.format("/projects/%d/columns", getId())) - .fetch(GHProjectColumn.class) - .lateBind(this); + public URL getHtmlUrl() throws IOException { + return GitHubClient.parseURL(html_url); } /** - * Delete. + * Gets owner. * + * @return the owner * @throws IOException * the io exception */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHObject getOwner() throws IOException { + if (owner == null) { + try { + if (owner_url.contains("/orgs/")) { + owner = root().createRequest().withUrlPath(getOwnerUrl().getPath()).fetch(GHOrganization.class); + } else if (owner_url.contains("/users/")) { + owner = root().createRequest().withUrlPath(getOwnerUrl().getPath()).fetch(GHUser.class); + } else if (owner_url.contains("/repos/")) { + String[] pathElements = getOwnerUrl().getPath().split("/"); + owner = GHRepository.read(root(), pathElements[1], pathElements[2]); + } + } catch (FileNotFoundException e) { + return null; + } + } + return owner; } /** - * Gets body. + * Gets owner url. * - * @return the body + * @return the owner url */ - public String getBody() { - return body; + public URL getOwnerUrl() { + return GitHubClient.parseURL(owner_url); } /** - * Gets creator. + * Gets name. * - * @return the creator + * @return the name */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getCreator() { - return creator; + public String getName() { + return name; } /** - * Gets the html url. + * Gets body. * - * @return the html url + * @return the body */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public String getBody() { + return body; } /** - * Gets name. + * Gets number. * - * @return the name + * @return the number */ - public String getName() { - return name; + public int getNumber() { + return number; } /** - * Gets number. + * Gets state. * - * @return the number + * @return the state */ - public int getNumber() { - return number; + public ProjectState getState() { + return Enum.valueOf(ProjectState.class, state.toUpperCase(Locale.ENGLISH)); } /** - * Gets owner. + * Gets creator. * - * @return the owner - * @throws IOException - * the io exception + * @return the creator */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHObject getOwner() throws IOException { - if (owner == null) { - try { - if (ownerUrl.contains("/orgs/")) { - owner = root().createRequest().withUrlPath(getOwnerUrl().getPath()).fetch(GHOrganization.class); - } else if (ownerUrl.contains("/users/")) { - owner = root().createRequest().withUrlPath(getOwnerUrl().getPath()).fetch(GHUser.class); - } else if (ownerUrl.contains("/repos/")) { - String[] pathElements = getOwnerUrl().getPath().split("/"); - owner = GHRepository.read(root(), pathElements[1], pathElements[2]); - } - } catch (FileNotFoundException e) { - return null; - } - } - return owner; + public GHUser getCreator() { + return creator; } /** - * Gets owner url. + * Wrap gh project. * - * @return the owner url + * @param repo + * the repo + * @return the gh project */ - public URL getOwnerUrl() { - return GitHubClient.parseURL(ownerUrl); + GHProject lateBind(GHRepository repo) { + this.owner = repo; + return this; + } + + private void edit(String key, Object value) throws IOException { + root().createRequest().method("PATCH").with(key, value).withUrlPath(getApiRoute()).send(); } /** - * Gets state. + * Gets api route. * - * @return the state + * @return the api route */ - public ProjectState getState() { - return Enum.valueOf(ProjectState.class, state.toUpperCase(Locale.ENGLISH)); + protected String getApiRoute() { + return "/projects/" + getId(); } /** - * List columns paged iterable. + * Sets name. * - * @return the paged iterable + * @param name + * the name + * @throws IOException + * the io exception */ - public PagedIterable listColumns() { - final GHProject project = this; - return root().createRequest() - .withUrlPath(String.format("/projects/%d/columns", getId())) - .toIterable(GHProjectColumn[].class, item -> item.lateBind(project)); + public void setName(String name) throws IOException { + edit("name", name); } /** @@ -223,15 +198,39 @@ public void setBody(String body) throws IOException { } /** - * Sets name. + * The enum ProjectState. + */ + public enum ProjectState { + + /** The open. */ + OPEN, + /** The closed. */ + CLOSED + } + + /** + * Sets state. * - * @param name - * the name + * @param state + * the state * @throws IOException * the io exception */ - public void setName(String name) throws IOException { - edit("name", name); + public void setState(ProjectState state) throws IOException { + edit("state", state.toString().toLowerCase()); + } + + /** + * The enum ProjectStateFilter. + */ + public static enum ProjectStateFilter { + + /** The all. */ + ALL, + /** The open. */ + OPEN, + /** The closed. */ + CLOSED } /** @@ -260,39 +259,44 @@ public void setPublic(boolean isPublic) throws IOException { } /** - * Sets state. + * Delete. * - * @param state - * the state * @throws IOException * the io exception */ - public void setState(ProjectState state) throws IOException { - edit("state", state.toString().toLowerCase()); - } - - private void edit(String key, Object value) throws IOException { - root().createRequest().method("PATCH").with(key, value).withUrlPath(getApiRoute()).send(); + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } /** - * Gets api route. + * List columns paged iterable. * - * @return the api route + * @return the paged iterable + * @throws IOException + * the io exception */ - protected String getApiRoute() { - return "/projects/" + getId(); + public PagedIterable listColumns() throws IOException { + final GHProject project = this; + return root().createRequest() + .withUrlPath(String.format("/projects/%d/columns", getId())) + .toIterable(GHProjectColumn[].class, item -> item.lateBind(project)); } /** - * Wrap gh project. + * Create column gh project column. * - * @param repo - * the repo - * @return the gh project + * @param name + * the name + * @return the gh project column + * @throws IOException + * the io exception */ - GHProject lateBind(GHRepository repo) { - this.owner = repo; - return this; + public GHProjectColumn createColumn(String name) throws IOException { + return root().createRequest() + .method("POST") + .with("name", name) + .withUrlPath(String.format("/projects/%d/columns", getId())) + .fetch(GHProjectColumn.class) + .lateBind(this); } } diff --git a/src/main/java/org/kohsuke/github/GHProjectCard.java b/src/main/java/org/kohsuke/github/GHProjectCard.java index 6b3d7321b8..ddfba5c152 100644 --- a/src/main/java/org/kohsuke/github/GHProjectCard.java +++ b/src/main/java/org/kohsuke/github/GHProjectCard.java @@ -15,28 +15,71 @@ */ public class GHProjectCard extends GHObject { - private boolean archived; + /** + * Create default GHProjectCard instance + */ + public GHProjectCard() { + } + private GHProject project; private GHProjectColumn column; - private String contentUrl, projectUrl, columnUrl; - private GHUser creator; private String note; - private GHProject project; + private GHUser creator; + private String content_url, project_url, column_url; + private boolean archived; + /** - * Create default GHProjectCard instance + * Gets the html url. + * + * @return the html url + * @throws IOException + * Signals that an I/O exception has occurred. */ - public GHProjectCard() { + public URL getHtmlUrl() throws IOException { + return null; } /** - * Delete. + * Wrap gh project card. * + * @param root + * the root + * @return the gh project card + */ + GHProjectCard lateBind(GitHub root) { + return this; + } + + /** + * Wrap gh project card. + * + * @param column + * the column + * @return the gh project card + */ + GHProjectCard lateBind(GHProjectColumn column) { + this.column = column; + this.project = column.project; + return lateBind(column.root()); + } + + /** + * Gets project. + * + * @return the project * @throws IOException * the io exception */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHProject getProject() throws IOException { + if (project == null) { + try { + project = root().createRequest().withUrlPath(getProjectUrl().getPath()).fetch(GHProject.class); + } catch (FileNotFoundException e) { + } + } + return project; } /** @@ -60,15 +103,6 @@ public GHProjectColumn getColumn() throws IOException { return column; } - /** - * Gets column url. - * - * @return the column url - */ - public URL getColumnUrl() { - return GitHubClient.parseURL(columnUrl); - } - /** * Gets content if present. Might be a {@link GHPullRequest} or a {@link GHIssue}. * @@ -77,10 +111,10 @@ public URL getColumnUrl() { * the io exception */ public GHIssue getContent() throws IOException { - if (StringUtils.isEmpty(contentUrl)) + if (StringUtils.isEmpty(content_url)) return null; try { - if (contentUrl.contains("/pulls")) { + if (content_url.contains("/pulls")) { return root().createRequest().withUrlPath(getContentUrl().getPath()).fetch(GHPullRequest.class); } else { return root().createRequest().withUrlPath(getContentUrl().getPath()).fetch(GHIssue.class); @@ -91,12 +125,12 @@ public GHIssue getContent() throws IOException { } /** - * Gets content url. + * Gets note. * - * @return the content url + * @return the note */ - public URL getContentUrl() { - return GitHubClient.parseURL(contentUrl); + public String getNote() { + return note; } /** @@ -110,48 +144,30 @@ public GHUser getCreator() { } /** - * Gets the html url. - * - * @return the html url - */ - public URL getHtmlUrl() { - return null; - } - - /** - * Gets note. + * Gets content url. * - * @return the note + * @return the content url */ - public String getNote() { - return note; + public URL getContentUrl() { + return GitHubClient.parseURL(content_url); } /** - * Gets project. + * Gets project url. * - * @return the project - * @throws IOException - * the io exception + * @return the project url */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHProject getProject() throws IOException { - if (project == null) { - try { - project = root().createRequest().withUrlPath(getProjectUrl().getPath()).fetch(GHProject.class); - } catch (FileNotFoundException e) { - } - } - return project; + public URL getProjectUrl() { + return GitHubClient.parseURL(project_url); } /** - * Gets project url. + * Gets column url. * - * @return the project url + * @return the column url */ - public URL getProjectUrl() { - return GitHubClient.parseURL(projectUrl); + public URL getColumnUrl() { + return GitHubClient.parseURL(column_url); } /** @@ -164,27 +180,27 @@ public boolean isArchived() { } /** - * Sets archived. + * Sets note. * - * @param archived - * the archived + * @param note + * the note * @throws IOException * the io exception */ - public void setArchived(boolean archived) throws IOException { - edit("archived", archived); + public void setNote(String note) throws IOException { + edit("note", note); } /** - * Sets note. + * Sets archived. * - * @param note - * the note + * @param archived + * the archived * @throws IOException * the io exception */ - public void setNote(String note) throws IOException { - edit("note", note); + public void setArchived(boolean archived) throws IOException { + edit("archived", archived); } private void edit(String key, Object value) throws IOException { @@ -201,26 +217,12 @@ protected String getApiRoute() { } /** - * Wrap gh project card. - * - * @param column - * the column - * @return the gh project card - */ - GHProjectCard lateBind(GHProjectColumn column) { - this.column = column; - this.project = column.project; - return lateBind(column.root()); - } - - /** - * Wrap gh project card. + * Delete. * - * @param root - * the root - * @return the gh project card + * @throws IOException + * the io exception */ - GHProjectCard lateBind(GitHub root) { - return this; + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } } diff --git a/src/main/java/org/kohsuke/github/GHProjectColumn.java b/src/main/java/org/kohsuke/github/GHProjectColumn.java index 8b7b0f272c..5af7afec7a 100644 --- a/src/main/java/org/kohsuke/github/GHProjectColumn.java +++ b/src/main/java/org/kohsuke/github/GHProjectColumn.java @@ -14,73 +14,39 @@ */ public class GHProjectColumn extends GHObject { - private String name; - - private String projectUrl; - - /** The project. */ - protected GHProject project; /** * Create default GHProjectColumn instance */ public GHProjectColumn() { } - /** - * Create card gh project card. - * - * @param issue - * the issue - * @return the gh project card - * @throws IOException - * the io exception - */ - public GHProjectCard createCard(GHIssue issue) throws IOException { - String contentType = issue instanceof GHPullRequest ? "PullRequest" : "Issue"; - return root().createRequest() - .method("POST") - .with("content_type", contentType) - .with("content_id", issue.getId()) - .withUrlPath(String.format("/projects/columns/%d/cards", getId())) - .fetch(GHProjectCard.class) - .lateBind(this); - } + /** The project. */ + protected GHProject project; - /** - * Create card gh project card. - * - * @param note - * the note - * @return the gh project card - * @throws IOException - * the io exception - */ - public GHProjectCard createCard(String note) throws IOException { - return root().createRequest() - .method("POST") - .with("note", note) - .withUrlPath(String.format("/projects/columns/%d/cards", getId())) - .fetch(GHProjectCard.class) - .lateBind(this); - } + private String name; + private String project_url; /** - * Delete. + * Wrap gh project column. * - * @throws IOException - * the io exception + * @param root + * the root + * @return the gh project column */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + GHProjectColumn lateBind(GitHub root) { + return this; } /** - * Gets name. + * Wrap gh project column. * - * @return the name + * @param project + * the project + * @return the gh project column */ - public String getName() { - return name; + GHProjectColumn lateBind(GHProject project) { + this.project = project; + return lateBind(project.root()); } /** @@ -102,24 +68,21 @@ public GHProject getProject() throws IOException { } /** - * Gets project url. + * Gets name. * - * @return the project url + * @return the name */ - public URL getProjectUrl() { - return GitHubClient.parseURL(projectUrl); + public String getName() { + return name; } /** - * List cards paged iterable. + * Gets project url. * - * @return the paged iterable + * @return the project url */ - public PagedIterable listCards() { - final GHProjectColumn column = this; - return root().createRequest() - .withUrlPath(String.format("/projects/columns/%d/cards", getId())) - .toIterable(GHProjectCard[].class, item -> item.lateBind(column)); + public URL getProjectUrl() { + return GitHubClient.parseURL(project_url); } /** @@ -148,25 +111,64 @@ protected String getApiRoute() { } /** - * Wrap gh project column. + * Delete. * - * @param project - * the project - * @return the gh project column + * @throws IOException + * the io exception */ - GHProjectColumn lateBind(GHProject project) { - this.project = project; - return lateBind(project.root()); + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } /** - * Wrap gh project column. + * List cards paged iterable. * - * @param root - * the root - * @return the gh project column + * @return the paged iterable + * @throws IOException + * the io exception */ - GHProjectColumn lateBind(GitHub root) { - return this; + public PagedIterable listCards() throws IOException { + final GHProjectColumn column = this; + return root().createRequest() + .withUrlPath(String.format("/projects/columns/%d/cards", getId())) + .toIterable(GHProjectCard[].class, item -> item.lateBind(column)); + } + + /** + * Create card gh project card. + * + * @param note + * the note + * @return the gh project card + * @throws IOException + * the io exception + */ + public GHProjectCard createCard(String note) throws IOException { + return root().createRequest() + .method("POST") + .with("note", note) + .withUrlPath(String.format("/projects/columns/%d/cards", getId())) + .fetch(GHProjectCard.class) + .lateBind(this); + } + + /** + * Create card gh project card. + * + * @param issue + * the issue + * @return the gh project card + * @throws IOException + * the io exception + */ + public GHProjectCard createCard(GHIssue issue) throws IOException { + String contentType = issue instanceof GHPullRequest ? "PullRequest" : "Issue"; + return root().createRequest() + .method("POST") + .with("content_type", contentType) + .with("content_id", issue.getId()) + .withUrlPath(String.format("/projects/columns/%d/cards", getId())) + .fetch(GHProjectCard.class) + .lateBind(this); } } diff --git a/src/main/java/org/kohsuke/github/GHProjectsV2Item.java b/src/main/java/org/kohsuke/github/GHProjectsV2Item.java index 10f581bf80..43d0224489 100644 --- a/src/main/java/org/kohsuke/github/GHProjectsV2Item.java +++ b/src/main/java/org/kohsuke/github/GHProjectsV2Item.java @@ -1,10 +1,9 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import org.kohsuke.github.internal.EnumUtils; +import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -25,41 +24,25 @@ public class GHProjectsV2Item extends GHObject { /** - * The Enum ContentType. + * Create default GHProjectsV2Item instance */ - public enum ContentType { - - /** The draftissue. */ - DRAFTISSUE, - /** The issue. */ - ISSUE, - /** The pullrequest. */ - PULLREQUEST, - /** The unknown. */ - UNKNOWN; + public GHProjectsV2Item() { } - private String archivedAt; + private String projectNodeId; private String contentNodeId; private String contentType; private GHUser creator; - private String projectNodeId; - - /** - * Create default GHProjectsV2Item instance - */ - public GHProjectsV2Item() { - } + private String archivedAt; /** - * Gets the archived at. + * Gets the project node id. * - * @return the archived at + * @return the project node id */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getArchivedAt() { - return GitHubClient.parseInstant(archivedAt); + public String getProjectNodeId() { + return projectNodeId; } /** @@ -84,11 +67,22 @@ public ContentType getContentType() { * Gets the creator. * * @return the creator + * @throws IOException + * Signals that an I/O exception has occurred. */ - public GHUser getCreator() { + public GHUser getCreator() throws IOException { return root().intern(creator); } + /** + * Gets the archived at. + * + * @return the archived at + */ + public Date getArchivedAt() { + return GitHubClient.parseDate(archivedAt); + } + /** * Gets the html url. * @@ -99,11 +93,17 @@ public URL getHtmlUrl() { } /** - * Gets the project node id. - * - * @return the project node id + * The Enum ContentType. */ - public String getProjectNodeId() { - return projectNodeId; + public enum ContentType { + + /** The issue. */ + ISSUE, + /** The draftissue. */ + DRAFTISSUE, + /** The pullrequest. */ + PULLREQUEST, + /** The unknown. */ + UNKNOWN; } } diff --git a/src/main/java/org/kohsuke/github/GHProjectsV2ItemChanges.java b/src/main/java/org/kohsuke/github/GHProjectsV2ItemChanges.java index 9ab551c3ad..d9636537ef 100644 --- a/src/main/java/org/kohsuke/github/GHProjectsV2ItemChanges.java +++ b/src/main/java/org/kohsuke/github/GHProjectsV2ItemChanges.java @@ -1,10 +1,8 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.kohsuke.github.internal.EnumUtils; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -14,25 +12,45 @@ * Note that this is best effort only as nothing is documented in the GitHub documentation. */ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") -public class GHProjectsV2ItemChanges extends GitHubBridgeAdapterObject { +public class GHProjectsV2ItemChanges { /** - * The Enum FieldType. + * Create default GHProjectsV2ItemChanges instance */ - public enum FieldType { + public GHProjectsV2ItemChanges() { + } - /** The date. */ - DATE, - /** The iteration. */ - ITERATION, - /** The number. */ - NUMBER, - /** The single select. */ - SINGLE_SELECT, - /** The text. */ - TEXT, - /** The unknown. */ - UNKNOWN; + private FieldValue fieldValue; + + private FromToDate archivedAt; + + private FromTo previousProjectsV2ItemNodeId; + + /** + * Gets the field value. + * + * @return the field value + */ + public FieldValue getFieldValue() { + return fieldValue; + } + + /** + * Gets the archived at. + * + * @return the archived at + */ + public FromToDate getArchivedAt() { + return archivedAt; + } + + /** + * Gets the previous projects V 2 item node id. + * + * @return the previous projects V 2 item node id + */ + public FromTo getPreviousProjectsV2ItemNodeId() { + return previousProjectsV2ItemNodeId; } /** @@ -40,15 +58,15 @@ public enum FieldType { */ public static class FieldValue { - private String fieldNodeId; - - private String fieldType; /** * Create default FieldValue instance */ public FieldValue() { } + private String fieldNodeId; + private String fieldType; + /** * Gets the field node id. * @@ -73,15 +91,15 @@ public FieldType getFieldType() { */ public static class FromTo { - private String from; - - private String to; /** * Create default FromTo instance */ public FromTo() { } + private String from; + private String to; + /** * Gets the from. * @@ -106,23 +124,22 @@ public String getTo() { */ public static class FromToDate { - private String from; - - private String to; /** * Create default FromToDate instance */ public FromToDate() { } + private String from; + private String to; + /** * Gets the from. * * @return the from */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getFrom() { - return GitHubClient.parseInstant(from); + public Date getFrom() { + return GitHubClient.parseDate(from); } /** @@ -130,48 +147,27 @@ public Instant getFrom() { * * @return the to */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getTo() { - return GitHubClient.parseInstant(to); + public Date getTo() { + return GitHubClient.parseDate(to); } } - private FromToDate archivedAt; - - private FieldValue fieldValue; - - private FromTo previousProjectsV2ItemNodeId; - /** - * Create default GHProjectsV2ItemChanges instance - */ - public GHProjectsV2ItemChanges() { - } - - /** - * Gets the archived at. - * - * @return the archived at - */ - public FromToDate getArchivedAt() { - return archivedAt; - } - - /** - * Gets the field value. - * - * @return the field value + * The Enum FieldType. */ - public FieldValue getFieldValue() { - return fieldValue; - } + public enum FieldType { - /** - * Gets the previous projects V 2 item node id. - * - * @return the previous projects V 2 item node id - */ - public FromTo getPreviousProjectsV2ItemNodeId() { - return previousProjectsV2ItemNodeId; + /** The text. */ + TEXT, + /** The number. */ + NUMBER, + /** The date. */ + DATE, + /** The single select. */ + SINGLE_SELECT, + /** The iteration. */ + ITERATION, + /** The unknown. */ + UNKNOWN; } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 6062102c59..a355b07a12 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -23,13 +23,11 @@ */ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -48,243 +46,152 @@ public class GHPullRequest extends GHIssue implements Refreshable { /** - * The status of auto merging a {@linkplain GHPullRequest}. - * + * Create default GHPullRequest instance */ - @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") - public static class AutoMerge { - - private String commitMessage; - - private String commitTitle; - private GHUser enabledBy; - private MergeMethod mergeMethod; - /** - * Create default AutoMerge instance - */ - public AutoMerge() { - } - - /** - * the message of the commit, if e.g. {@linkplain MergeMethod#SQUASH} is used for the auto merge. - * - * @return the message of the commit - */ - public String getCommitMessage() { - return commitMessage; - } - - /** - * the title of the commit, if e.g. {@linkplain MergeMethod#SQUASH} is used for the auto merge. - * - * @return the title of the commit - */ - public String getCommitTitle() { - return commitTitle; - } - - /** - * The user who enabled the auto merge of the pull request. - * - * @return the {@linkplain GHUser} - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getEnabledBy() { - return enabledBy; - } - - /** - * The merge method of the auto merge. - * - * @return the {@linkplain MergeMethod} - */ - public MergeMethod getMergeMethod() { - return mergeMethod; - } + public GHPullRequest() { } - /** The enum MergeMethod. */ - public enum MergeMethod { - - /** The merge. */ - MERGE, - /** The rebase. */ - REBASE, - /** The squash. */ - SQUASH - } private static final String COMMENTS_ACTION = "/comments"; - private static final String REQUEST_REVIEWERS = "/requested_reviewers"; - private AutoMerge autoMerge; - private GHCommitPointer base; - private int changedFiles; - private int deletions; + private String patch_url, diff_url, issue_url; + private GHCommitPointer base; + private String merged_at; private GHCommitPointer head; - private String mergeCommitSha; - private Boolean mergeable; - private String mergeableState; - private boolean merged, maintainerCanModify; - private String mergedAt; // details that are only available when obtained from ID - private GHUser mergedBy; - private String patchUrl, diffUrl, issueUrl; - private GHUser[] requestedReviewers; - - // pull request reviewers - - private GHTeam[] requestedTeams; - private int reviewComments, additions, commits; + private GHUser merged_by; + private int review_comments, additions, commits; + private boolean merged, maintainer_can_modify; /** The draft. */ // making these package private to all for testing boolean draft; + private Boolean mergeable; + private int deletions; + private String mergeable_state; + private int changed_files; + private String merge_commit_sha; + private AutoMerge auto_merge; + + // pull request reviewers + + private GHUser[] requested_reviewers; + private GHTeam[] requested_teams; /** - * Create default GHPullRequest instance + * Wrap up. + * + * @param owner + * the owner + * @return the GH pull request */ - public GHPullRequest() { + GHPullRequest wrapUp(GHRepository owner) { + this.wrap(owner); + return this; } /** - * Can maintainer modify boolean. + * Gets the api route. * - * @return the boolean - * @throws IOException - * the io exception + * @return the api route */ - public boolean canMaintainerModify() throws IOException { - populate(); - return maintainerCanModify; + @Override + protected String getApiRoute() { + if (owner == null) { + // Issues returned from search to do not have an owner. Attempt to use url. + final URL url = Objects.requireNonNull(getUrl(), "Missing instance URL!"); + // The url sourced above is of the form '/repos///issues/', which + // subsequently issues requests against the `/issues/` handler, causing a 404 when + // asking for, say, a list of commits associated with a PR. Replace the `/issues/` + // with `/pulls/` to avoid that. + return StringUtils.prependIfMissing(url.toString().replace(root().getApiUrl(), ""), "/") + .replace("/issues/", "/pulls/"); + } + return "/repos/" + owner.getOwnerName() + "/" + owner.getName() + "/pulls/" + number; } /** - * Create review gh pull request review builder. + * The status of auto merging a pull request. * - * @return the gh pull request review builder + * @return the {@linkplain AutoMerge} or {@code null} if no auto merge is set. */ - public GHPullRequestReviewBuilder createReview() { - return new GHPullRequestReviewBuilder(this); + public AutoMerge getAutoMerge() { + return auto_merge; } /** - * Create gh pull request review comment builder. + * The URL of the patch file. like https://github.com/jenkinsci/jenkins/pull/100.patch * - * @return the gh pull request review comment builder. + * @return the patch url */ - public GHPullRequestReviewCommentBuilder createReviewComment() { - return new GHPullRequestReviewCommentBuilder(this); + public URL getPatchUrl() { + return GitHubClient.parseURL(patch_url); } /** - * Create review comment gh pull request review comment. + * The URL of the patch file. like https://github.com/jenkinsci/jenkins/pull/100.patch * - * @param body - * the body - * @param sha - * the sha - * @param path - * the path - * @param position - * the position - * @return the gh pull request review comment - * @throws IOException - * the io exception - * @deprecated use {@link #createReviewComment()} + * @return the issue url */ - @Deprecated - public GHPullRequestReviewComment createReviewComment(String body, String sha, String path, int position) - throws IOException { - return createReviewComment().body(body).commitId(sha).path(path).position(position).create(); + public URL getIssueUrl() { + return GitHubClient.parseURL(issue_url); } /** - * Request to enable auto merge for a pull request. - * - * @param authorEmail - * The email address to associate with this merge. - * @param clientMutationId - * A unique identifier for the client performing the mutation. - * @param commitBody - * Commit body to use for the commit when the PR is mergable; if omitted, a default message will be used. - * NOTE: when merging with a merge queue any input value for commit message is ignored. - * @param commitHeadline - * Commit headline to use for the commit when the PR is mergable; if omitted, a default message will be - * used. NOTE: when merging with a merge queue any input value for commit headline is ignored. - * @param expectedHeadOid - * The expected head OID of the pull request. - * @param mergeMethod - * The merge method to use. If omitted, defaults to `MERGE`. NOTE: when merging with a merge queue any - * input value for merge method is ignored. - * @throws IOException - * the io exception + * This points to where the change should be pulled into, but I'm not really sure what exactly it means. + * + * @return the base */ - public void enablePullRequestAutoMerge(String authorEmail, - String clientMutationId, - String commitBody, - String commitHeadline, - String expectedHeadOid, - MergeMethod mergeMethod) throws IOException { - - StringBuilder inputBuilder = new StringBuilder(); - addParameter(inputBuilder, "pullRequestId", this.getNodeId()); - addOptionalParameter(inputBuilder, "authorEmail", authorEmail); - addOptionalParameter(inputBuilder, "clientMutationId", clientMutationId); - addOptionalParameter(inputBuilder, "commitBody", commitBody); - addOptionalParameter(inputBuilder, "commitHeadline", commitHeadline); - addOptionalParameter(inputBuilder, "expectedHeadOid", expectedHeadOid); - addOptionalParameter(inputBuilder, "mergeMethod", mergeMethod); - - String graphqlBody = "mutation EnableAutoMerge { enablePullRequestAutoMerge(input: {" + inputBuilder + "}) { " - + "pullRequest { id } } }"; - - root().createGraphQLRequest(graphqlBody).sendGraphQL(); + public GHCommitPointer getBase() { + return base; + } - refresh(); + /** + * The change that should be pulled. The tip of the commits to merge. + * + * @return the head + */ + public GHCommitPointer getHead() { + return head; } /** - * Gets additions. + * The diff file, like https://github.com/jenkinsci/jenkins/pull/100.diff * - * @return the additions - * @throws IOException - * the io exception + * @return the diff url */ - public int getAdditions() throws IOException { - populate(); - return additions; + public URL getDiffUrl() { + return GitHubClient.parseURL(diff_url); } /** - * The status of auto merging a pull request. + * Gets merged at. * - * @return the {@linkplain AutoMerge} or {@code null} if no auto merge is set. + * @return the merged at */ - public AutoMerge getAutoMerge() { - return autoMerge; + public Date getMergedAt() { + return GitHubClient.parseDate(merged_at); } /** - * This points to where the change should be pulled into, but I'm not really sure what exactly it means. + * Gets the closed by. * - * @return the base + * @return the closed by */ - public GHCommitPointer getBase() { - return base; + @Override + public GHUser getClosedBy() { + return null; } /** - * Gets changed files. + * Gets the pull request. * - * @return the changed files - * @throws IOException - * the io exception + * @return the pull request */ - public int getChangedFiles() throws IOException { - populate(); - return changedFiles; + @Override + public PullRequest getPullRequest() { + return null; } // @@ -292,76 +199,88 @@ public int getChangedFiles() throws IOException { // /** - * Gets the closed by. + * Gets merged by. * - * @return the closed by + * @return the merged by + * @throws IOException + * the io exception */ - @Override - public GHUser getClosedBy() { - return null; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getMergedBy() throws IOException { + populate(); + return merged_by; } /** - * Gets the number of commits. + * Gets review comments. * - * @return the number of commits + * @return the review comments * @throws IOException * the io exception */ - public int getCommits() throws IOException { + public int getReviewComments() throws IOException { populate(); - return commits; + return review_comments; } /** - * Gets deletions. + * Gets additions. * - * @return the deletions + * @return the additions * @throws IOException * the io exception */ - public int getDeletions() throws IOException { + public int getAdditions() throws IOException { populate(); - return deletions; + return additions; } /** - * The diff file, like https://github.com/jenkinsci/jenkins/pull/100.diff + * Gets the number of commits. * - * @return the diff url + * @return the number of commits + * @throws IOException + * the io exception */ - public URL getDiffUrl() { - return GitHubClient.parseURL(diffUrl); + public int getCommits() throws IOException { + populate(); + return commits; } /** - * The change that should be pulled. The tip of the commits to merge. + * Is merged boolean. * - * @return the head + * @return the boolean + * @throws IOException + * the io exception */ - public GHCommitPointer getHead() { - return head; + public boolean isMerged() throws IOException { + populate(); + return merged; } /** - * The URL of the patch file. like https://github.com/jenkinsci/jenkins/pull/100.patch + * Can maintainer modify boolean. * - * @return the issue url + * @return the boolean + * @throws IOException + * the io exception */ - public URL getIssueUrl() { - return GitHubClient.parseURL(issueUrl); + public boolean canMaintainerModify() throws IOException { + populate(); + return maintainer_can_modify; } /** - * See GitHub blog post + * Is draft boolean. * - * @return the merge commit sha + * @return the boolean * @throws IOException * the io exception */ - public String getMergeCommitSha() throws IOException { + public boolean isDraft() throws IOException { populate(); - return mergeCommitSha; + return draft; } /** @@ -379,57 +298,60 @@ public Boolean getMergeable() throws IOException { } /** - * Gets mergeable state. + * for test purposes only. * - * @return the mergeable state - * @throws IOException - * the io exception + * @return the mergeable no refresh */ - public String getMergeableState() throws IOException { - populate(); - return mergeableState; + Boolean getMergeableNoRefresh() { + return mergeable; } /** - * Gets merged at. + * Gets deletions. * - * @return the merged at + * @return the deletions + * @throws IOException + * the io exception */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getMergedAt() { - return GitHubClient.parseInstant(mergedAt); + public int getDeletions() throws IOException { + populate(); + return deletions; } /** - * Gets merged by. + * Gets mergeable state. * - * @return the merged by + * @return the mergeable state * @throws IOException * the io exception */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getMergedBy() throws IOException { + public String getMergeableState() throws IOException { populate(); - return mergedBy; + return mergeable_state; } /** - * The URL of the patch file. like https://github.com/jenkinsci/jenkins/pull/100.patch + * Gets changed files. * - * @return the patch url + * @return the changed files + * @throws IOException + * the io exception */ - public URL getPatchUrl() { - return GitHubClient.parseURL(patchUrl); + public int getChangedFiles() throws IOException { + populate(); + return changed_files; } /** - * Gets the pull request. + * See GitHub blog post * - * @return the pull request + * @return the merge commit sha + * @throws IOException + * the io exception */ - @Override - public PullRequest getPullRequest() { - return null; + public String getMergeCommitSha() throws IOException { + populate(); + return merge_commit_sha; } /** @@ -440,8 +362,8 @@ public PullRequest getPullRequest() { * the io exception */ public List getRequestedReviewers() throws IOException { - refresh(requestedReviewers); - return Collections.unmodifiableList(Arrays.asList(requestedReviewers)); + refresh(requested_reviewers); + return Collections.unmodifiableList(Arrays.asList(requested_reviewers)); } /** @@ -452,55 +374,37 @@ public List getRequestedReviewers() throws IOException { * the io exception */ public List getRequestedTeams() throws IOException { - refresh(requestedTeams); - return Collections.unmodifiableList(Arrays.asList(requestedTeams)); + refresh(requested_teams); + return Collections.unmodifiableList(Arrays.asList(requested_teams)); } /** - * Gets review comments. - * - * @return the review comments - * @throws IOException - * the io exception - */ - public int getReviewComments() throws IOException { - populate(); - return reviewComments; - } - - /** - * Is draft boolean. + * Fully populate the data by retrieving missing data. * - * @return the boolean - * @throws IOException - * the io exception + *

+ * Depending on the original API call where this object is created, it may not contain everything. */ - public boolean isDraft() throws IOException { - populate(); - return draft; + private void populate() throws IOException { + if (mergeable_state != null) + return; // already populated + refresh(); } /** - * Is merged boolean. + * Repopulates this object. * - * @return the boolean * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public boolean isMerged() throws IOException { - populate(); - return merged; - } + public void refresh() throws IOException { + if (isOffline()) { + return; // cannot populate, will have to live with what we have + } - /** - * Retrieves all the commits associated to this pull request. - * - * @return the paged iterable - */ - public PagedIterable listCommits() { - return root().createRequest() - .withUrlPath(String.format("%s/commits", getApiRoute())) - .toIterable(GHPullRequestCommitDetail[].class, item -> item.wrapUp(this)); + // we do not want to use getUrl() here as it points to the issues API + // and not the pull request one + URL absoluteUrl = GitHubRequest.getApiURL(root().getApiUrl(), getApiRoute()); + root().createRequest().setRawUrlPath(absoluteUrl.toString()).fetchInto(this).wrapUp(owner); } /** @@ -517,100 +421,79 @@ public PagedIterable listFiles() { .toIterable(GHPullRequestFileDetail[].class, null); } + /** + * Retrieves all the reviews associated to this pull request. + * + * @return the paged iterable + */ + public PagedIterable listReviews() { + return root().createRequest() + .withUrlPath(String.format("%s/reviews", getApiRoute())) + .toIterable(GHPullRequestReview[].class, item -> item.wrapUp(this)); + } + /** * Obtains all the review comments associated with this pull request. * * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listReviewComments() { + public PagedIterable listReviewComments() throws IOException { return root().createRequest() .withUrlPath(getApiRoute() + COMMENTS_ACTION) .toIterable(GHPullRequestReviewComment[].class, item -> item.wrapUp(this)); } /** - * Retrieves all the reviews associated to this pull request. + * Retrieves all the commits associated to this pull request. * * @return the paged iterable */ - public PagedIterable listReviews() { + public PagedIterable listCommits() { return root().createRequest() - .withUrlPath(String.format("%s/reviews", getApiRoute())) - .toIterable(GHPullRequestReview[].class, item -> item.wrapUp(this)); + .withUrlPath(String.format("%s/commits", getApiRoute())) + .toIterable(GHPullRequestCommitDetail[].class, item -> item.wrapUp(this)); } /** - * Merge this pull request. - * - *

- * The equivalent of the big green "Merge pull request" button. + * Create review gh pull request review builder. * - * @param msg - * Commit message. If null, the default one will be used. - * @throws IOException - * the io exception + * @return the gh pull request review builder */ - public void merge(String msg) throws IOException { - merge(msg, null); + public GHPullRequestReviewBuilder createReview() { + return new GHPullRequestReviewBuilder(this); } /** - * Merge this pull request. - * - *

- * The equivalent of the big green "Merge pull request" button. + * Create gh pull request review comment builder. * - * @param msg - * Commit message. If null, the default one will be used. - * @param sha - * SHA that pull request head must match to allow merge. - * @throws IOException - * the io exception + * @return the gh pull request review comment builder. */ - public void merge(String msg, String sha) throws IOException { - merge(msg, sha, null); + public GHPullRequestReviewCommentBuilder createReviewComment() { + return new GHPullRequestReviewCommentBuilder(this); } /** - * Merge this pull request, using the specified merge method. - * - *

- * The equivalent of the big green "Merge pull request" button. + * Create review comment gh pull request review comment. * - * @param msg - * Commit message. If null, the default one will be used. + * @param body + * the body * @param sha * the sha - * @param method - * SHA that pull request head must match to allow merge. + * @param path + * the path + * @param position + * the position + * @return the gh pull request review comment * @throws IOException * the io exception + * @deprecated use {@link #createReviewComment()} */ - public void merge(String msg, String sha, MergeMethod method) throws IOException { - root().createRequest() - .method("PUT") - .with("commit_message", msg) - .with("sha", sha) - .with("merge_method", method) - .withUrlPath(getApiRoute() + "/merge") - .send(); - } - - /** - * Repopulates this object. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - public void refresh() throws IOException { - if (isOffline()) { - return; // cannot populate, will have to live with what we have - } - - // we do not want to use getUrl() here as it points to the issues API - // and not the pull request one - URL absoluteUrl = GitHubRequest.getApiURL(root().getApiUrl(), getApiRoute()); - root().createRequest().setRawUrlPath(absoluteUrl.toString()).fetchInto(this).wrapUp(owner); + @Deprecated + public GHPullRequestReviewComment createReviewComment(String body, String sha, String path, int position) + throws IOException { + return createReviewComment().body(body).commitId(sha).path(path).position(position).create(); } /** @@ -680,71 +563,127 @@ public void updateBranch() throws IOException { .send(); } - private void addOptionalParameter(StringBuilder inputBuilder, String name, Object value) { - if (value != null) { - addParameter(inputBuilder, name, value); - } - } - - private void addParameter(StringBuilder inputBuilder, String name, Object value) { - Objects.requireNonNull(value); - String formatString = " %s: \"%s\""; - if (value instanceof Enum) { - formatString = " %s: %s"; - } - - inputBuilder.append(String.format(formatString, name, value)); - } - /** - * Fully populate the data by retrieving missing data. + * Merge this pull request. * *

- * Depending on the original API call where this object is created, it may not contain everything. + * The equivalent of the big green "Merge pull request" button. + * + * @param msg + * Commit message. If null, the default one will be used. + * @throws IOException + * the io exception */ - private void populate() throws IOException { - if (mergeableState != null) - return; // already populated - refresh(); + public void merge(String msg) throws IOException { + merge(msg, null); } /** - * Gets the api route. + * Merge this pull request. * - * @return the api route + *

+ * The equivalent of the big green "Merge pull request" button. + * + * @param msg + * Commit message. If null, the default one will be used. + * @param sha + * SHA that pull request head must match to allow merge. + * @throws IOException + * the io exception */ - @Override - protected String getApiRoute() { - if (owner == null) { - // Issues returned from search to do not have an owner. Attempt to use url. - final URL url = Objects.requireNonNull(getUrl(), "Missing instance URL!"); - // The url sourced above is of the form '/repos///issues/', which - // subsequently issues requests against the `/issues/` handler, causing a 404 when - // asking for, say, a list of commits associated with a PR. Replace the `/issues/` - // with `/pulls/` to avoid that. - return StringUtils.prependIfMissing(url.toString().replace(root().getApiUrl(), ""), "/") - .replace("/issues/", "/pulls/"); - } - return "/repos/" + owner.getOwnerName() + "/" + owner.getName() + "/pulls/" + number; + public void merge(String msg, String sha) throws IOException { + merge(msg, sha, null); } /** - * for test purposes only. + * Merge this pull request, using the specified merge method. * - * @return the mergeable no refresh + *

+ * The equivalent of the big green "Merge pull request" button. + * + * @param msg + * Commit message. If null, the default one will be used. + * @param sha + * the sha + * @param method + * SHA that pull request head must match to allow merge. + * @throws IOException + * the io exception */ - Boolean getMergeableNoRefresh() { - return mergeable; + public void merge(String msg, String sha, MergeMethod method) throws IOException { + root().createRequest() + .method("PUT") + .with("commit_message", msg) + .with("sha", sha) + .with("merge_method", method) + .withUrlPath(getApiRoute() + "/merge") + .send(); + } + + /** The enum MergeMethod. */ + public enum MergeMethod { + + /** The merge. */ + MERGE, + /** The squash. */ + SQUASH, + /** The rebase. */ + REBASE } + /** - * Wrap up. + * The status of auto merging a {@linkplain GHPullRequest}. * - * @param owner - * the owner - * @return the GH pull request */ - GHPullRequest wrapUp(GHRepository owner) { - this.wrap(owner); - return this; + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") + public static class AutoMerge { + + /** + * Create default AutoMerge instance + */ + public AutoMerge() { + } + + private GHUser enabled_by; + private MergeMethod merge_method; + private String commit_title; + private String commit_message; + + /** + * The user who enabled the auto merge of the pull request. + * + * @return the {@linkplain GHUser} + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getEnabledBy() { + return enabled_by; + } + + /** + * The merge method of the auto merge. + * + * @return the {@linkplain MergeMethod} + */ + public MergeMethod getMergeMethod() { + return merge_method; + } + + /** + * the title of the commit, if e.g. {@linkplain MergeMethod#SQUASH} is used for the auto merge. + * + * @return the title of the commit + */ + public String getCommitTitle() { + return commit_title; + } + + /** + * the message of the commit, if e.g. {@linkplain MergeMethod#SQUASH} is used for the auto merge. + * + * @return the message of the commit + */ + public String getCommitMessage() { + return commit_message; + } } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestChanges.java b/src/main/java/org/kohsuke/github/GHPullRequestChanges.java index d70e283f30..a866b33b38 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestChanges.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestChanges.java @@ -11,6 +11,43 @@ @SuppressFBWarnings("UWF_UNWRITTEN_FIELD") public class GHPullRequestChanges { + /** + * Create default GHPullRequestChanges instance + */ + public GHPullRequestChanges() { + } + + private GHCommitPointer base; + private GHFrom title; + private GHFrom body; + + /** + * Old target branch for pull request. + * + * @return old target branch info (or null if not changed) + */ + public GHCommitPointer getBase() { + return base; + } + + /** + * Old pull request title. + * + * @return old pull request title (or null if not changed) + */ + public GHFrom getTitle() { + return title; + } + + /** + * Old pull request body. + * + * @return old pull request body (or null if not changed) + */ + public GHFrom getBody() { + return body; + } + /** * The Class GHCommitPointer. * @@ -18,15 +55,15 @@ public class GHPullRequestChanges { */ public static class GHCommitPointer { - private GHFrom ref; - - private GHFrom sha; /** * Create default GHCommitPointer instance */ public GHCommitPointer() { } + private GHFrom ref; + private GHFrom sha; + /** * Named ref to the commit. This (from value) appears to be a "short ref" that doesn't include "refs/heads/" * portion. @@ -52,14 +89,14 @@ public GHFrom getSha() { */ public static class GHFrom { - private String from; - /** * Create default GHFrom instance */ public GHFrom() { } + private String from; + /** * Previous value that was changed. * @@ -69,41 +106,4 @@ public String getFrom() { return from; } } - private GHCommitPointer base; - private GHFrom body; - - private GHFrom title; - - /** - * Create default GHPullRequestChanges instance - */ - public GHPullRequestChanges() { - } - - /** - * Old target branch for pull request. - * - * @return old target branch info (or null if not changed) - */ - public GHCommitPointer getBase() { - return base; - } - - /** - * Old pull request body. - * - * @return old pull request body (or null if not changed) - */ - public GHFrom getBody() { - return body; - } - - /** - * Old pull request title. - * - * @return old pull request title (or null if not changed) - */ - public GHFrom getTitle() { - return title; - } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java b/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java index 565270ef1b..f01da64f74 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java @@ -40,17 +40,74 @@ justification = "JSON API") public class GHPullRequestCommitDetail { + /** + * Create default GHPullRequestCommitDetail instance + */ + public GHPullRequestCommitDetail() { + } + + private GHPullRequest owner; + + /** + * Wrap up. + * + * @param owner + * the owner + */ + void wrapUp(GHPullRequest owner) { + this.owner = owner; + } + + /** + * The type Tree. + */ + public static class Tree { + + /** + * Create default Tree instance + */ + public Tree() { + } + + /** The sha. */ + String sha; + + /** The url. */ + String url; + + /** + * Gets sha. + * + * @return the sha + */ + public String getSha() { + return sha; + } + + /** + * Gets url. + * + * @return the url + */ + public URL getUrl() { + return GitHubClient.parseURL(url); + } + } + /** * The type Commit. */ public static class Commit { + /** + * Create default Commit instance + */ + public Commit() { + } + /** The author. */ GitUser author; - /** The comment count. */ - Integer commentCount; - /** The committer. */ GitUser committer; @@ -63,11 +120,8 @@ public static class Commit { /** The url. */ String url; - /** - * Create default Commit instance - */ - public Commit() { - } + /** The comment count. */ + int comment_count; /** * Gets author. @@ -79,41 +133,39 @@ public GitUser getAuthor() { } /** - * Gets comment count. + * Gets committer. * - * @return the comment count + * @return the committer */ - public Integer getCommentCount() { - return commentCount; + public GitUser getCommitter() { + return committer; } /** - * Gets comment count. + * Gets message. * - * @return the comment count - * @deprecated Use {@link #getCommentCount()} + * @return the message */ - @Deprecated - public int getComment_count() { - return getCommentCount(); + public String getMessage() { + return message; } /** - * Gets committer. + * Gets url. * - * @return the committer + * @return the url */ - public GitUser getCommitter() { - return committer; + public URL getUrl() { + return GitHubClient.parseURL(url); } /** - * Gets message. + * Gets comment count. * - * @return the message + * @return the comment count */ - public String getMessage() { - return message; + public int getComment_count() { + return comment_count; } /** @@ -124,15 +176,6 @@ public String getMessage() { public Tree getTree() { return tree; } - - /** - * Gets url. - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(url); - } } /** @@ -140,49 +183,20 @@ public URL getUrl() { */ public static class CommitPointer { - /** The html url. */ - String htmlUrl; - - /** The sha. */ - String sha; - - /** The url. */ - String url; - /** * Create default CommitPointer instance */ public CommitPointer() { } - /** - * Gets html url. - * - * @return the html url - */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); - } + /** The sha. */ + String sha; - /** - * Gets html url. - * - * @return the html url - * @deprecated Use {@link #getHtmlUrl()} - */ - @Deprecated - public URL getHtml_url() { - return getHtmlUrl(); - } + /** The url. */ + String url; - /** - * Gets sha. - * - * @return the sha - */ - public String getSha() { - return sha; - } + /** The html url. */ + String html_url; /** * Gets url. @@ -192,23 +206,14 @@ public String getSha() { public URL getUrl() { return GitHubClient.parseURL(url); } - } - - /** - * The type Tree. - */ - public static class Tree { - - /** The sha. */ - String sha; - - /** The url. */ - String url; /** - * Create default Tree instance + * Gets html url. + * + * @return the html url */ - public Tree() { + public URL getHtml_url() { + return GitHubClient.parseURL(html_url); } /** @@ -219,41 +224,42 @@ public Tree() { public String getSha() { return sha; } - - /** - * Gets url. - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(url); - } } - private GHPullRequest owner; - - /** The comments url. */ - String commentsUrl; + /** The sha. */ + String sha; /** The commit. */ Commit commit; + /** The url. */ + String url; + /** The html url. */ - String htmlUrl; + String html_url; + + /** The comments url. */ + String comments_url; /** The parents. */ CommitPointer[] parents; - /** The sha. */ - String sha; - - /** The url. */ - String url; + /** + * Gets sha. + * + * @return the sha + */ + public String getSha() { + return sha; + } /** - * Create default GHPullRequestCommitDetail instance + * Gets commit. + * + * @return the commit */ - public GHPullRequestCommitDetail() { + public Commit getCommit() { + return commit; } /** @@ -266,21 +272,21 @@ public URL getApiUrl() { } /** - * Gets comments url. + * Gets url. * - * @return the comments url + * @return the url */ - public URL getCommentsUrl() { - return GitHubClient.parseURL(commentsUrl); + public URL getUrl() { + return GitHubClient.parseURL(html_url); } /** - * Gets commit. + * Gets comments url. * - * @return the commit + * @return the comments url */ - public Commit getCommit() { - return commit; + public URL getCommentsUrl() { + return GitHubClient.parseURL(comments_url); } /** @@ -293,32 +299,4 @@ public CommitPointer[] getParents() { System.arraycopy(parents, 0, newValue, 0, parents.length); return newValue; } - - /** - * Gets sha. - * - * @return the sha - */ - public String getSha() { - return sha; - } - - /** - * Gets url. - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(htmlUrl); - } - - /** - * Wrap up. - * - * @param owner - * the owner - */ - void wrapUp(GHPullRequest owner) { - this.owner = owner; - } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java b/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java index 147d30b4d3..2a316f49e7 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java @@ -35,43 +35,72 @@ */ public class GHPullRequestFileDetail { + /** + * Create default GHPullRequestFileDetail instance + */ + public GHPullRequestFileDetail() { + } + + /** The sha. */ + String sha; + + /** The filename. */ + String filename; + + /** The status. */ + String status; + /** The additions. */ int additions; - /** The blob url. */ - String blobUrl; + /** The deletions. */ + int deletions; /** The changes. */ int changes; - /** The contents url. */ - String contentsUrl; + /** The blob url. */ + String blob_url; - /** The deletions. */ - int deletions; + /** The raw url. */ + String raw_url; - /** The filename. */ - String filename; + /** The contents url. */ + String contents_url; /** The patch. */ String patch; /** The previous filename. */ - String previousFilename; - - /** The raw url. */ - String rawUrl; + String previous_filename; - /** The sha. */ - String sha; + /** + * Gets sha of the file (not commit sha). + * + * @return the sha + * @see List pull requests + * files + */ + public String getSha() { + return sha; + } - /** The status. */ - String status; + /** + * Gets filename. + * + * @return the filename + */ + public String getFilename() { + return filename; + } /** - * Create default GHPullRequestFileDetail instance + * Gets status (added/modified/deleted). + * + * @return the status */ - public GHPullRequestFileDetail() { + public String getStatus() { + return status; } /** @@ -84,12 +113,12 @@ public int getAdditions() { } /** - * Gets blob url. + * Gets deletions. * - * @return the blob url + * @return the deletions */ - public URL getBlobUrl() { - return GitHubClient.parseURL(blobUrl); + public int getDeletions() { + return deletions; } /** @@ -102,30 +131,30 @@ public int getChanges() { } /** - * Gets contents url. + * Gets blob url. * - * @return the contents url + * @return the blob url */ - public URL getContentsUrl() { - return GitHubClient.parseURL(contentsUrl); + public URL getBlobUrl() { + return GitHubClient.parseURL(blob_url); } /** - * Gets deletions. + * Gets raw url. * - * @return the deletions + * @return the raw url */ - public int getDeletions() { - return deletions; + public URL getRawUrl() { + return GitHubClient.parseURL(raw_url); } /** - * Gets filename. + * Gets contents url. * - * @return the filename + * @return the contents url */ - public String getFilename() { - return filename; + public URL getContentsUrl() { + return GitHubClient.parseURL(contents_url); } /** @@ -143,35 +172,6 @@ public String getPatch() { * @return the previous filename */ public String getPreviousFilename() { - return previousFilename; - } - - /** - * Gets raw url. - * - * @return the raw url - */ - public URL getRawUrl() { - return GitHubClient.parseURL(rawUrl); - } - - /** - * Gets sha of the file (not commit sha). - * - * @return the sha - * @see List pull requests - * files - */ - public String getSha() { - return sha; - } - - /** - * Gets status (added/modified/deleted). - * - * @return the status - */ - public String getStatus() { - return status; + return previous_filename; } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestQueryBuilder.java b/src/main/java/org/kohsuke/github/GHPullRequestQueryBuilder.java index 9ac028613d..05f905e389 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestQueryBuilder.java @@ -8,21 +8,6 @@ * @see GHRepository#queryPullRequests() GHRepository#queryPullRequests() */ public class GHPullRequestQueryBuilder extends GHQueryBuilder { - /** - * The enum Sort. - */ - public enum Sort { - - /** The created. */ - CREATED, - /** The long running. */ - LONG_RUNNING, - /** The popularity. */ - POPULARITY, - /** The updated. */ - UPDATED - } - private final GHRepository repo; /** @@ -37,26 +22,14 @@ public enum Sort { } /** - * Base gh pull request query builder. - * - * @param base - * the base - * @return the gh pull request query builder - */ - public GHPullRequestQueryBuilder base(String base) { - req.with("base", base); - return this; - } - - /** - * Direction gh pull request query builder. + * State gh pull request query builder. * - * @param d - * the d + * @param state + * the state * @return the gh pull request query builder */ - public GHPullRequestQueryBuilder direction(GHDirection d) { - req.with("direction", d); + public GHPullRequestQueryBuilder state(GHIssueState state) { + req.with("state", state); return this; } @@ -76,14 +49,15 @@ public GHPullRequestQueryBuilder head(String head) { } /** - * List. + * Base gh pull request query builder. * - * @return the paged iterable + * @param base + * the base + * @return the gh pull request query builder */ - @Override - public PagedIterable list() { - return req.withUrlPath(repo.getApiTailUrl("pulls")) - .toIterable(GHPullRequest[].class, item -> item.wrapUp(repo)); + public GHPullRequestQueryBuilder base(String base) { + req.with("base", base); + return this; } /** @@ -99,14 +73,40 @@ public GHPullRequestQueryBuilder sort(Sort sort) { } /** - * State gh pull request query builder. + * The enum Sort. + */ + public enum Sort { + + /** The created. */ + CREATED, + /** The updated. */ + UPDATED, + /** The popularity. */ + POPULARITY, + /** The long running. */ + LONG_RUNNING + } + + /** + * Direction gh pull request query builder. * - * @param state - * the state + * @param d + * the d * @return the gh pull request query builder */ - public GHPullRequestQueryBuilder state(GHIssueState state) { - req.with("state", state); + public GHPullRequestQueryBuilder direction(GHDirection d) { + req.with("direction", d); return this; } + + /** + * List. + * + * @return the paged iterable + */ + @Override + public PagedIterable list() { + return req.withUrlPath(repo.getApiTailUrl("pulls")) + .toIterable(GHPullRequest[].class, item -> item.wrapUp(repo)); + } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java index 10eb93ba4e..3f7e04540d 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReview.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java @@ -23,12 +23,10 @@ */ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Date; import javax.annotation.CheckForNull; @@ -43,48 +41,42 @@ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") public class GHPullRequestReview extends GHObject { - private String body; - - private String commitId; - - private String htmlUrl; - private GHPullRequestReviewState state; - private String submittedAt; - private GHUser user; - /** The owner. */ - GHPullRequest owner; /** * Create default GHPullRequestReview instance */ public GHPullRequestReview() { } + /** The owner. */ + GHPullRequest owner; + + private String body; + private GHUser user; + private String commit_id; + private GHPullRequestReviewState state; + private String submitted_at; + private String html_url; + /** - * Deletes this review. + * Wrap up. * - * @throws IOException - * the io exception + * @param owner + * the owner + * @return the GH pull request review */ - public void delete() throws IOException { - owner.root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + GHPullRequestReview wrapUp(GHPullRequest owner) { + this.owner = owner; + return this; } /** - * Dismisses this review. + * Gets the pull request to which this review is associated. * - * @param message - * the message - * @throws IOException - * the io exception + * @return the parent */ - public void dismiss(String message) throws IOException { - owner.root() - .createRequest() - .method("PUT") - .with("message", message) - .withUrlPath(getApiRoute() + "/dismissals") - .send(); - state = GHPullRequestReviewState.DISMISSED; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHPullRequest getParent() { + return owner; } /** @@ -96,26 +88,34 @@ public String getBody() { return body; } + /** + * Gets the user who posted this review. + * + * @return the user + * @throws IOException + * the io exception + */ + public GHUser getUser() throws IOException { + return owner == null || owner.isOffline() ? user : owner.root().getUser(user.login); + } + /** * Gets commit id. * * @return the commit id */ public String getCommitId() { - return commitId; + return commit_id; } /** - * Since this method does not exist, we forward this value. + * Gets state. * - * @return the created at - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the state */ - @Override - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCreatedAt() throws IOException { - return getSubmittedAt(); + @CheckForNull + public GHPullRequestReviewState getState() { + return state; } /** @@ -124,63 +124,39 @@ public Instant getCreatedAt() throws IOException { * @return the html url */ public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); - } - - /** - * Gets the pull request to which this review is associated. - * - * @return the parent - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHPullRequest getParent() { - return owner; + return GitHubClient.parseURL(html_url); } /** - * Gets state. + * Gets api route. * - * @return the state + * @return the api route */ - @CheckForNull - public GHPullRequestReviewState getState() { - return state; + protected String getApiRoute() { + return owner.getApiRoute() + "/reviews/" + getId(); } /** * When was this resource created?. * * @return the submitted at - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getSubmittedAt() { - return GitHubClient.parseInstant(submittedAt); - } - - /** - * Gets the user who posted this review. - * - * @return the user * @throws IOException * the io exception */ - public GHUser getUser() throws IOException { - if (user != null) { - return owner.root().getUser(user.getLogin()); - } - return null; + public Date getSubmittedAt() throws IOException { + return GitHubClient.parseDate(submitted_at); } /** - * Obtains all the review comments associated with this pull request review. + * Since this method does not exist, we forward this value. * - * @return the paged iterable + * @return the created at + * @throws IOException + * Signals that an I/O exception has occurred. */ - public PagedIterable listReviewComments() { - return owner.root() - .createRequest() - .withUrlPath(getApiRoute() + "/comments") - .toIterable(GHPullRequestReviewComment[].class, item -> item.wrapUp(owner)); + @Override + public Date getCreatedAt() throws IOException { + return getSubmittedAt(); } /** @@ -206,23 +182,44 @@ public void submit(String body, GHPullRequestReviewEvent event) throws IOExcepti } /** - * Gets api route. + * Deletes this review. * - * @return the api route + * @throws IOException + * the io exception */ - protected String getApiRoute() { - return owner.getApiRoute() + "/reviews/" + getId(); + public void delete() throws IOException { + owner.root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } /** - * Wrap up. + * Dismisses this review. * - * @param owner - * the owner - * @return the GH pull request review + * @param message + * the message + * @throws IOException + * the io exception */ - GHPullRequestReview wrapUp(GHPullRequest owner) { - this.owner = owner; - return this; + public void dismiss(String message) throws IOException { + owner.root() + .createRequest() + .method("PUT") + .with("message", message) + .withUrlPath(getApiRoute() + "/dismissals") + .send(); + state = GHPullRequestReviewState.DISMISSED; + } + + /** + * Obtains all the review comments associated with this pull request review. + * + * @return the paged iterable + * @throws IOException + * the io exception + */ + public PagedIterable listReviewComments() throws IOException { + return owner.root() + .createRequest() + .withUrlPath(getApiRoute() + "/comments") + .toIterable(GHPullRequestReviewComment[].class, item -> item.wrapUp(owner)); } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java index a971c53d70..c536dbfdc3 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java @@ -12,6 +12,131 @@ * @see GHPullRequest#createReview() GHPullRequest#createReview() */ public class GHPullRequestReviewBuilder { + private final GHPullRequest pr; + private final Requester builder; + private final List comments = new ArrayList<>(); + + /** + * Instantiates a new GH pull request review builder. + * + * @param pr + * the pr + */ + GHPullRequestReviewBuilder(GHPullRequest pr) { + this.pr = pr; + this.builder = pr.root().createRequest(); + } + + // public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event, + // List comments) throws IOException + + /** + * The SHA of the commit that needs a review. Not using the latest commit SHA may render your review comment + * outdated if a subsequent commit modifies the line you specify as the position. Defaults to the most recent commit + * in the pull request when you do not specify a value. + * + * @param commitId + * the commit id + * @return the gh pull request review builder + */ + public GHPullRequestReviewBuilder commitId(String commitId) { + builder.with("commit_id", commitId); + return this; + } + + /** + * Required when using REQUEST_CHANGES or COMMENT for the event parameter. The body text of the pull request review. + * + * @param body + * the body + * @return the gh pull request review builder + */ + public GHPullRequestReviewBuilder body(String body) { + builder.with("body", body); + return this; + } + + /** + * The review action you want to perform. The review actions include: APPROVE, REQUEST_CHANGES, or COMMENT. By + * leaving this blank, you set the review action state to PENDING, which means you will need to + * {@linkplain GHPullRequestReview#submit(String, GHPullRequestReviewEvent) submit the pull request review} when you + * are ready. + * + * @param event + * the event + * @return the gh pull request review builder + */ + public GHPullRequestReviewBuilder event(GHPullRequestReviewEvent event) { + builder.with("event", event.action()); + return this; + } + + /** + * Comment gh pull request review builder. + * + * @param body + * Text of the review comment. + * @param path + * The relative path to the file that necessitates a review comment. + * @param position + * The position in the diff where you want to add a review comment. Note this value is not the same as + * the line number in the file. For help finding the position value, read the note below. + * @return the gh pull request review builder + */ + public GHPullRequestReviewBuilder comment(String body, String path, int position) { + comments.add(new DraftReviewComment(body, path, position)); + return this; + } + + /** + * Add a multi-line comment to the gh pull request review builder. + * + * @param body + * Text of the review comment. + * @param path + * The relative path to the file that necessitates a review comment. + * @param startLine + * The first line in the pull request diff that the multi-line comment applies to. + * @param endLine + * The last line of the range that the comment applies to. + * @return the gh pull request review builder + */ + public GHPullRequestReviewBuilder multiLineComment(String body, String path, int startLine, int endLine) { + this.comments.add(new MultilineDraftReviewComment(body, path, startLine, endLine)); + return this; + } + + /** + * Add a single line comment to the gh pull request review builder. + * + * @param body + * Text of the review comment. + * @param path + * The relative path to the file that necessitates a review comment. + * @param line + * The line of the blob in the pull request diff that the comment applies to. + * @return the gh pull request review builder + */ + public GHPullRequestReviewBuilder singleLineComment(String body, String path, int line) { + this.comments.add(new SingleLineDraftReviewComment(body, path, line)); + return this; + } + + /** + * Create gh pull request review. + * + * @return the gh pull request review + * @throws IOException + * the io exception + */ + public GHPullRequestReview create() throws IOException { + return builder.method("POST") + .with("comments", comments) + .withUrlPath(pr.getApiRoute() + "/reviews") + .fetch(GHPullRequestReview.class) + .wrapUp(pr); + } + /** * Common properties of the review comments, regardless of how the comment is positioned on the gh pull request. */ @@ -30,6 +155,7 @@ private interface ReviewComment { */ String getPath(); } + /** * Single line comment using the relative position in the diff. */ @@ -61,26 +187,31 @@ public int getPosition() { return position; } } + /** * Multi-line comment. */ static class MultilineDraftReviewComment implements ReviewComment { private final String body; - private final int line; private final String path; - private final int startLine; + private final int line; + private final int start_line; MultilineDraftReviewComment(final String body, final String path, final int startLine, final int line) { this.body = body; this.path = path; this.line = line; - this.startLine = startLine; + this.start_line = startLine; } public String getBody() { return this.body; } + public String getPath() { + return this.path; + } + /** * Gets end line of the comment. * @@ -90,17 +221,13 @@ public int getLine() { return line; } - public String getPath() { - return this.path; - } - /** * Gets start line of the comment. * * @return the start line of the comment. */ public int getStartLine() { - return startLine; + return start_line; } } @@ -109,8 +236,8 @@ public int getStartLine() { */ static class SingleLineDraftReviewComment implements ReviewComment { private final String body; - private final int line; private final String path; + private final int line; SingleLineDraftReviewComment(final String body, final String path, final int line) { this.body = body; @@ -122,6 +249,10 @@ public String getBody() { return this.body; } + public String getPath() { + return this.path; + } + /** * Gets line of the comment. * @@ -130,136 +261,5 @@ public String getBody() { public int getLine() { return line; } - - public String getPath() { - return this.path; - } - } - - // public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event, - // List comments) throws IOException - - private final Requester builder; - - private final List comments = new ArrayList<>(); - - private final GHPullRequest pr; - - /** - * Instantiates a new GH pull request review builder. - * - * @param pr - * the pr - */ - GHPullRequestReviewBuilder(GHPullRequest pr) { - this.pr = pr; - this.builder = pr.root().createRequest(); - } - - /** - * Required when using REQUEST_CHANGES or COMMENT for the event parameter. The body text of the pull request review. - * - * @param body - * the body - * @return the gh pull request review builder - */ - public GHPullRequestReviewBuilder body(String body) { - builder.with("body", body); - return this; - } - - /** - * Comment gh pull request review builder. - * - * @param body - * Text of the review comment. - * @param path - * The relative path to the file that necessitates a review comment. - * @param position - * The position in the diff where you want to add a review comment. Note this value is not the same as - * the line number in the file. For help finding the position value, read the note below. - * @return the gh pull request review builder - */ - public GHPullRequestReviewBuilder comment(String body, String path, int position) { - comments.add(new DraftReviewComment(body, path, position)); - return this; - } - - /** - * The SHA of the commit that needs a review. Not using the latest commit SHA may render your review comment - * outdated if a subsequent commit modifies the line you specify as the position. Defaults to the most recent commit - * in the pull request when you do not specify a value. - * - * @param commitId - * the commit id - * @return the gh pull request review builder - */ - public GHPullRequestReviewBuilder commitId(String commitId) { - builder.with("commit_id", commitId); - return this; - } - - /** - * Create gh pull request review. - * - * @return the gh pull request review - * @throws IOException - * the io exception - */ - public GHPullRequestReview create() throws IOException { - return builder.method("POST") - .with("comments", comments) - .withUrlPath(pr.getApiRoute() + "/reviews") - .fetch(GHPullRequestReview.class) - .wrapUp(pr); - } - - /** - * The review action you want to perform. The review actions include: APPROVE, REQUEST_CHANGES, or COMMENT. By - * leaving this blank, you set the review action state to PENDING, which means you will need to - * {@linkplain GHPullRequestReview#submit(String, GHPullRequestReviewEvent) submit the pull request review} when you - * are ready. - * - * @param event - * the event - * @return the gh pull request review builder - */ - public GHPullRequestReviewBuilder event(GHPullRequestReviewEvent event) { - builder.with("event", event.action()); - return this; - } - - /** - * Add a multi-line comment to the gh pull request review builder. - * - * @param body - * Text of the review comment. - * @param path - * The relative path to the file that necessitates a review comment. - * @param startLine - * The first line in the pull request diff that the multi-line comment applies to. - * @param endLine - * The last line of the range that the comment applies to. - * @return the gh pull request review builder - */ - public GHPullRequestReviewBuilder multiLineComment(String body, String path, int startLine, int endLine) { - this.comments.add(new MultilineDraftReviewComment(body, path, startLine, endLine)); - return this; - } - - /** - * Add a single line comment to the gh pull request review builder. - * - * @param body - * Text of the review comment. - * @param path - * The relative path to the file that necessitates a review comment. - * @param line - * The line of the blob in the pull request diff that the comment applies to. - * @return the gh pull request review builder - */ - public GHPullRequestReviewBuilder singleLineComment(String body, String path, int line) { - this.comments.add(new SingleLineDraftReviewComment(body, path, line)); - return this; } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index a21378ef86..34f47474ec 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -43,139 +43,114 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable { /** - * The side of the diff to which the comment applies + * Create default GHPullRequestReviewComment instance */ - public static enum Side { - /** Left side */ - LEFT, - /** Right side */ - RIGHT, - /** Unknown side */ - UNKNOWN; - - /** - * From. - * - * @param value - * the value - * @return the status - */ - public static Side from(String value) { - return EnumUtils.getEnumOrDefault(Side.class, value, Side.UNKNOWN); - } - + public GHPullRequestReviewComment() { } - private GHCommentAuthorAssociation authorAssociation; + /** The owner. */ + GHPullRequest owner; + private Long pull_request_review_id = -1L; private String body; - private String bodyHtml; - private String bodyText; - private String commitId; - private String diffHunk; - private String htmlUrl; - private long inReplyToId = -1L; - private int line = -1; - private String originalCommitId; - private int originalLine = -1; - private int originalPosition = -1; - private Integer originalStartLine = -1; + private GHUser user; private String path; + private String html_url; + private String pull_request_url; private int position = -1; - private Long pullRequestReviewId = -1L; - private String pullRequestUrl; - private GHPullRequestReviewCommentReactions reactions; + private int original_position = -1; + private long in_reply_to_id = -1L; + private Integer start_line = -1; + private Integer original_start_line = -1; + private String start_side; + private int line = -1; + private int original_line = -1; private String side; - private Integer startLine = -1; - private String startSide; - private GHUser user; - /** The owner. */ - GHPullRequest owner; + private String diff_hunk; + private String commit_id; + private String original_commit_id; + private String body_html; + private String body_text; + private GHPullRequestReviewCommentReactions reactions; + private GHCommentAuthorAssociation author_association; /** - * Create default GHPullRequestReviewComment instance + * Wrap up. + * + * @param owner + * the owner + * @return the GH pull request review comment */ - public GHPullRequestReviewComment() { + GHPullRequestReviewComment wrapUp(GHPullRequest owner) { + this.owner = owner; + return this; } /** - * Creates the reaction. + * Gets the pull request to which this review comment is associated. * - * @param content - * the content - * @return the GH reaction - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the parent */ - public GHReaction createReaction(ReactionContent content) throws IOException { - return owner.root() - .createRequest() - .method("POST") - .with("content", content.getContent()) - .withUrlPath(getApiRoute() + "/reactions") - .fetch(GHReaction.class); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHPullRequest getParent() { + return owner; } /** - * Deletes this review comment. + * The comment itself. * - * @throws IOException - * the io exception + * @return the body */ - public void delete() throws IOException { - owner.root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + public String getBody() { + return body; } /** - * Delete reaction. + * Gets the user who posted this comment. * - * @param reaction - * the reaction + * @return the user * @throws IOException - * Signals that an I/O exception has occurred. + * the io exception */ - public void deleteReaction(GHReaction reaction) throws IOException { - owner.root() - .createRequest() - .method("DELETE") - .withUrlPath(getApiRoute(), "reactions", String.valueOf(reaction.getId())) - .send(); + public GHUser getUser() throws IOException { + return owner == null || owner.isOffline() ? user : owner.root().getUser(user.login); } /** - * Gets the author association to the project. + * Gets path. * - * @return the author association to the project + * @return the path */ - public GHCommentAuthorAssociation getAuthorAssociation() { - return authorAssociation; + public String getPath() { + return path; } /** - * The comment itself. + * Gets position. * - * @return the body + * @return the position */ - public String getBody() { - return body; + @CheckForNull + public int getPosition() { + return position; } /** - * Gets The body in html format. + * Gets original position. * - * @return {@link String} the body in html format + * @return the original position */ - public String getBodyHtml() { - return bodyHtml; + public int getOriginalPosition() { + return original_position; } /** - * Gets The body text. + * Gets diff hunk. * - * @return {@link String} the body text + * @return the diff hunk */ - public String getBodyText() { - return bodyText; + public String getDiffHunk() { + return diff_hunk; } /** @@ -184,25 +159,25 @@ public String getBodyText() { * @return the commit id */ public String getCommitId() { - return commitId; + return commit_id; } /** - * Gets diff hunk. + * Gets commit id. * - * @return the diff hunk + * @return the commit id */ - public String getDiffHunk() { - return diffHunk; + public String getOriginalCommitId() { + return original_commit_id; } /** - * Gets the html url. + * Gets the author association to the project. * - * @return the html url + * @return the author association to the project */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public GHCommentAuthorAssociation getAuthorAssociation() { + return author_association; } /** @@ -212,43 +187,47 @@ public URL getHtmlUrl() { */ @CheckForNull public long getInReplyToId() { - return inReplyToId; + return in_reply_to_id; } /** - * Gets The line of the blob to which the comment applies. The last line of the range for a multi-line comment. + * Gets the html url. * - * @return the line to which the comment applies + * @return the html url */ - public int getLine() { - return line; + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); } /** - * Gets commit id. + * Gets api route. * - * @return the commit id + * @return the api route */ - public String getOriginalCommitId() { - return originalCommitId; + protected String getApiRoute() { + return getApiRoute(false); } /** - * Gets The line of the blob to which the comment applies. The last line of the range for a multi-line comment. + * Gets api route. * - * @return the line to which the comment applies + * @param includePullNumber + * if true, includes the owning pull request's number in the route. + * + * @return the api route */ - public int getOriginalLine() { - return originalLine; + protected String getApiRoute(boolean includePullNumber) { + return "/repos/" + owner.getRepository().getFullName() + "/pulls" + + (includePullNumber ? "/" + owner.getNumber() : "") + "/comments/" + getId(); } /** - * Gets original position. + * Gets The first line of the range for a multi-line comment. * - * @return the original position + * @return the start line */ - public int getOriginalPosition() { - return originalPosition; + public int getStartLine() { + return start_line != null ? start_line : -1; } /** @@ -257,36 +236,44 @@ public int getOriginalPosition() { * @return the original start line */ public int getOriginalStartLine() { - return originalStartLine != null ? originalStartLine : -1; + return original_start_line != null ? original_start_line : -1; } /** - * Gets the pull request to which this review comment is associated. + * Gets The side of the first line of the range for a multi-line comment. * - * @return the parent + * @return {@link Side} the side of the first line */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHPullRequest getParent() { - return owner; + public Side getStartSide() { + return Side.from(start_side); } /** - * Gets path. + * Gets The line of the blob to which the comment applies. The last line of the range for a multi-line comment. * - * @return the path + * @return the line to which the comment applies */ - public String getPath() { - return path; + public int getLine() { + return line; } /** - * Gets position. + * Gets The line of the blob to which the comment applies. The last line of the range for a multi-line comment. * - * @return the position + * @return the line to which the comment applies */ - @CheckForNull - public int getPosition() { - return position; + public int getOriginalLine() { + return original_line; + } + + /** + * Gets The side of the diff to which the comment applies. The side of the last line of the range for a multi-line + * comment + * + * @return {@link Side} the side if the diff to which the comment applies + */ + public Side getSide() { + return Side.from(side); } /** @@ -295,7 +282,7 @@ public int getPosition() { * @return {@link Long} the ID of the pull request review */ public Long getPullRequestReviewId() { - return pullRequestReviewId != null ? pullRequestReviewId : -1; + return pull_request_review_id != null ? pull_request_review_id : -1; } /** @@ -304,67 +291,81 @@ public Long getPullRequestReviewId() { * @return {@link URL} the URL of the pull request */ public URL getPullRequestUrl() { - return GitHubClient.parseURL(pullRequestUrl); + return GitHubClient.parseURL(pull_request_url); } /** - * Gets the Reaction Rollup + * Gets The body in html format. * - * @return {@link GHPullRequestReviewCommentReactions} the reaction rollup + * @return {@link String} the body in html format */ - public GHPullRequestReviewCommentReactions getReactions() { - return reactions; + public String getBodyHtml() { + return body_html; } /** - * Gets The side of the diff to which the comment applies. The side of the last line of the range for a multi-line - * comment + * Gets The body text. * - * @return {@link Side} the side if the diff to which the comment applies + * @return {@link String} the body text */ - public Side getSide() { - return Side.from(side); + public String getBodyText() { + return body_text; } /** - * Gets The first line of the range for a multi-line comment. + * Gets the Reaction Rollup * - * @return the start line + * @return {@link GHPullRequestReviewCommentReactions} the reaction rollup */ - public int getStartLine() { - return startLine != null ? startLine : -1; + public GHPullRequestReviewCommentReactions getReactions() { + return reactions; } /** - * Gets The side of the first line of the range for a multi-line comment. - * - * @return {@link Side} the side of the first line + * The side of the diff to which the comment applies */ - public Side getStartSide() { - return Side.from(startSide); + public static enum Side { + /** Right side */ + RIGHT, + /** Left side */ + LEFT, + /** Unknown side */ + UNKNOWN; + + /** + * From. + * + * @param value + * the value + * @return the status + */ + public static Side from(String value) { + return EnumUtils.getEnumOrDefault(Side.class, value, Side.UNKNOWN); + } + } /** - * Gets the user who posted this comment. + * Updates the comment. * - * @return the user + * @param body + * the body * @throws IOException * the io exception */ - public GHUser getUser() throws IOException { - return owner.root().getUser(user.getLogin()); + public void update(String body) throws IOException { + owner.root().createRequest().method("PATCH").with("body", body).withUrlPath(getApiRoute()).fetchInto(this); + this.body = body; } /** - * List reactions. + * Deletes this review comment. * - * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listReactions() { - return owner.root() - .createRequest() - .withUrlPath(getApiRoute() + "/reactions") - .toIterable(GHReaction[].class, item -> owner.root()); + public void delete() throws IOException { + owner.root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } /** @@ -387,49 +388,48 @@ public GHPullRequestReviewComment reply(String body) throws IOException { } /** - * Updates the comment. + * Creates the reaction. * - * @param body - * the body + * @param content + * the content + * @return the GH reaction * @throws IOException - * the io exception - */ - public void update(String body) throws IOException { - owner.root().createRequest().method("PATCH").with("body", body).withUrlPath(getApiRoute()).fetchInto(this); - this.body = body; - } - - /** - * Gets api route. - * - * @return the api route + * Signals that an I/O exception has occurred. */ - protected String getApiRoute() { - return getApiRoute(false); + public GHReaction createReaction(ReactionContent content) throws IOException { + return owner.root() + .createRequest() + .method("POST") + .with("content", content.getContent()) + .withUrlPath(getApiRoute() + "/reactions") + .fetch(GHReaction.class); } /** - * Gets api route. - * - * @param includePullNumber - * if true, includes the owning pull request's number in the route. + * Delete reaction. * - * @return the api route + * @param reaction + * the reaction + * @throws IOException + * Signals that an I/O exception has occurred. */ - protected String getApiRoute(boolean includePullNumber) { - return "/repos/" + owner.getRepository().getFullName() + "/pulls" - + (includePullNumber ? "/" + owner.getNumber() : "") + "/comments/" + getId(); + public void deleteReaction(GHReaction reaction) throws IOException { + owner.root() + .createRequest() + .method("DELETE") + .withUrlPath(getApiRoute(), "reactions", String.valueOf(reaction.getId())) + .send(); } /** - * Wrap up. + * List reactions. * - * @param owner - * the owner - * @return the GH pull request review comment + * @return the paged iterable */ - GHPullRequestReviewComment wrapUp(GHPullRequest owner) { - this.owner = owner; - return this; + public PagedIterable listReactions() { + return owner.root() + .createRequest() + .withUrlPath(getApiRoute() + "/reactions") + .toIterable(GHReaction[].class, item -> owner.root()); } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewCommentBuilder.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewCommentBuilder.java index 82c1fe4f88..a3b267c9f9 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewCommentBuilder.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewCommentBuilder.java @@ -10,8 +10,8 @@ * @see GHPullRequest#createReviewComment() */ public class GHPullRequestReviewCommentBuilder { - private final Requester builder; private final GHPullRequest pr; + private final Requester builder; /** * Instantiates a new GH pull request review comment builder. @@ -24,6 +24,20 @@ public class GHPullRequestReviewCommentBuilder { this.builder = pr.root().createRequest(); } + /** + * The SHA of the commit that needs a review. Not using the latest commit SHA may render your review comment + * outdated if a subsequent commit modifies the line you specify as the position. Defaults to the most recent commit + * in the pull request when you do not specify a value. + * + * @param commitId + * the commit id + * @return the gh pull request review comment builder + */ + public GHPullRequestReviewCommentBuilder commitId(String commitId) { + builder.with("commit_id", commitId); + return this; + } + /** * The text of the pull request review comment. * @@ -37,31 +51,29 @@ public GHPullRequestReviewCommentBuilder body(String body) { } /** - * The SHA of the commit that needs a review. Not using the latest commit SHA may render your review comment - * outdated if a subsequent commit modifies the line you specify as the position. Defaults to the most recent commit - * in the pull request when you do not specify a value. + * The relative path to the file that necessitates a comment. * - * @param commitId - * the commit id + * @param path + * the path * @return the gh pull request review comment builder */ - public GHPullRequestReviewCommentBuilder commitId(String commitId) { - builder.with("commit_id", commitId); + public GHPullRequestReviewCommentBuilder path(String path) { + builder.with("path", path); return this; } /** - * Create gh pull request review comment. + * The position in the diff where you want to add a review comment. * + * @param position + * the position * @return the gh pull request review comment builder - * @throws IOException - * the io exception + * @implNote As position is deprecated in GitHub API, only keep this for internal usage (for retro-compatibility + * with {@link GHPullRequest#createReviewComment(String, String, String, int)}). */ - public GHPullRequestReviewComment create() throws IOException { - return builder.method("POST") - .withUrlPath(pr.getApiRoute() + "/comments") - .fetch(GHPullRequestReviewComment.class) - .wrapUp(pr); + GHPullRequestReviewCommentBuilder position(int position) { + builder.with("position", position); + return this; } /** @@ -99,66 +111,17 @@ public GHPullRequestReviewCommentBuilder lines(int startLine, int endLine) { } /** - * The relative path to the file that necessitates a comment. - * - * @param path - * the path - * @return the gh pull request review comment builder - */ - public GHPullRequestReviewCommentBuilder path(String path) { - builder.with("path", path); - return this; - } - - /** - * The side of the diff in the pull request that the comment applies to. - *

- * {@link #side(GHPullRequestReviewComment.Side)} and - * {@link #sides(GHPullRequestReviewComment.Side, GHPullRequestReviewComment.Side)} will overwrite each other's - * values. - * - * @param side - * side of the diff to which the comment applies - * @return the gh pull request review comment builder - */ - public GHPullRequestReviewCommentBuilder side(GHPullRequestReviewComment.Side side) { - builder.with("side", side); - builder.remove("start_side"); - return this; - } - - /** - * The sides of the diff in the pull request that the comment applies to. - *

- * {@link #side(GHPullRequestReviewComment.Side)} and - * {@link #sides(GHPullRequestReviewComment.Side, GHPullRequestReviewComment.Side)} will overwrite each other's - * values. - * - * @param startSide - * side of the diff to which the start of the comment applies - * @param endSide - * side of the diff to which the end of the comment applies - * @return the gh pull request review comment builder - */ - public GHPullRequestReviewCommentBuilder sides(GHPullRequestReviewComment.Side startSide, - GHPullRequestReviewComment.Side endSide) { - builder.with("start_side", startSide); - builder.with("side", endSide); - return this; - } - - /** - * The position in the diff where you want to add a review comment. + * Create gh pull request review comment. * - * @param position - * the position * @return the gh pull request review comment builder - * @implNote As position is deprecated in GitHub API, only keep this for internal usage (for retro-compatibility - * with {@link GHPullRequest#createReviewComment(String, String, String, int)}). + * @throws IOException + * the io exception */ - GHPullRequestReviewCommentBuilder position(int position) { - builder.with("position", position); - return this; + public GHPullRequestReviewComment create() throws IOException { + return builder.method("POST") + .withUrlPath(pr.getApiRoute() + "/comments") + .fetch(GHPullRequestReviewComment.class) + .wrapUp(pr); } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewCommentReactions.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewCommentReactions.java index d460872c9c..8a9624d694 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewCommentReactions.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewCommentReactions.java @@ -14,60 +14,60 @@ */ public class GHPullRequestReviewCommentReactions { - private int confused = -1; - - private int eyes = -1; - - private int heart = -1; - private int hooray = -1; - private int laugh = -1; - @JsonProperty("-1") - private int minusOne = -1; - @JsonProperty("+1") - private int plusOne = -1; - private int rocket = -1; - private int totalCount = -1; - private String url; /** * Create default GHPullRequestReviewCommentReactions instance */ public GHPullRequestReviewCommentReactions() { } + private String url; + + private int total_count = -1; + @JsonProperty("+1") + private int plus_one = -1; + @JsonProperty("-1") + private int minus_one = -1; + private int laugh = -1; + private int confused = -1; + private int heart = -1; + private int hooray = -1; + private int eyes = -1; + private int rocket = -1; + /** - * Gets the number of confused reactions + * Gets the URL of the comment's reactions * - * @return the number of confused reactions + * @return the URL of the comment's reactions */ - public int getConfused() { - return confused; + public URL getUrl() { + return GitHubClient.parseURL(url); } /** - * Gets the number of eyes reactions + * Gets the total count of reactions * - * @return the number of eyes reactions + * @return the number of total reactions */ - public int getEyes() { - return eyes; + public int getTotalCount() { + return total_count; } /** - * Gets the number of heart reactions + * Gets the number of +1 reactions * - * @return the number of heart reactions + * @return the number of +1 reactions */ - public int getHeart() { - return heart; + public int getPlusOne() { + return plus_one; } /** - * Gets the number of hooray reactions + * Gets the number of -1 reactions * - * @return the number of hooray reactions + * @return the number of -1 reactions */ - public int getHooray() { - return hooray; + public int getMinusOne() { + return minus_one; } /** @@ -80,47 +80,47 @@ public int getLaugh() { } /** - * Gets the number of -1 reactions + * Gets the number of confused reactions * - * @return the number of -1 reactions + * @return the number of confused reactions */ - public int getMinusOne() { - return minusOne; + public int getConfused() { + return confused; } /** - * Gets the number of +1 reactions + * Gets the number of heart reactions * - * @return the number of +1 reactions + * @return the number of heart reactions */ - public int getPlusOne() { - return plusOne; + public int getHeart() { + return heart; } /** - * Gets the number of rocket reactions + * Gets the number of hooray reactions * - * @return the number of rocket reactions + * @return the number of hooray reactions */ - public int getRocket() { - return rocket; + public int getHooray() { + return hooray; } /** - * Gets the total count of reactions + * Gets the number of eyes reactions * - * @return the number of total reactions + * @return the number of eyes reactions */ - public int getTotalCount() { - return totalCount; + public int getEyes() { + return eyes; } /** - * Gets the URL of the comment's reactions + * Gets the number of rocket reactions * - * @return the URL of the comment's reactions + * @return the number of rocket reactions */ - public URL getUrl() { - return GitHubClient.parseURL(url); + public int getRocket() { + return rocket; } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java index 8bffc057e8..025de45cad 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java @@ -29,14 +29,14 @@ */ public enum GHPullRequestReviewEvent { - /** The approve. */ - APPROVE, - /** The comment. */ - COMMENT, /** The pending. */ PENDING, + /** The approve. */ + APPROVE, /** The request changes. */ - REQUEST_CHANGES; + REQUEST_CHANGES, + /** The comment. */ + COMMENT; /** * Action. diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java index e90b07d369..3d755f9555 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java @@ -6,6 +6,9 @@ */ public enum GHPullRequestReviewState { + /** The pending. */ + PENDING, + /** The approved. */ APPROVED, @@ -16,10 +19,7 @@ public enum GHPullRequestReviewState { COMMENTED, /** The dismissed. */ - DISMISSED, - - /** The pending. */ - PENDING; + DISMISSED; /** * Action string. diff --git a/src/main/java/org/kohsuke/github/GHPullRequestSearchBuilder.java b/src/main/java/org/kohsuke/github/GHPullRequestSearchBuilder.java index 143f6e6ae2..970bfb34d2 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestSearchBuilder.java @@ -11,32 +11,6 @@ * issues and PRs */ public class GHPullRequestSearchBuilder extends GHSearchBuilder { - /** - * The sort order values. - */ - public enum Sort { - - /** The comments. */ - COMMENTS, - /** The created. */ - CREATED, - /** The relevance. */ - RELEVANCE, - /** The updated. */ - UPDATED - - } - - private static class PullRequestSearchResult extends SearchResult { - - private GHPullRequest[] items; - - @Override - GHPullRequest[] getItems(GitHub root) { - return items; - } - } - /** * Instantiates a new GH search builder. * @@ -48,14 +22,14 @@ GHPullRequest[] getItems(GitHub root) { } /** - * Assigned to gh pull request user. + * Repository gh pull request search builder. * - * @param u - * the gh user + * @param repository + * the repository * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder assigned(GHUser u) { - q("assignee", u.getLogin()); + public GHPullRequestSearchBuilder repo(GHRepository repository) { + q("repo", repository.getFullName()); return this; } @@ -72,125 +46,120 @@ public GHPullRequestSearchBuilder author(GHUser user) { } /** - * Base gh pull request search builder. + * CreatedByMe gh pull request search builder. * - * @param branch - * the base branch * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder base(GHBranch branch) { - q("base", branch.getName()); + public GHPullRequestSearchBuilder createdByMe() { + q("author:@me"); return this; } /** - * Closed gh pull request search builder. + * Assigned to gh pull request user. * - * @param closed - * the closed + * @param u + * the gh user * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder closed(LocalDate closed) { - q("closed", closed.format(DateTimeFormatter.ISO_DATE)); + public GHPullRequestSearchBuilder assigned(GHUser u) { + q("assignee", u.getLogin()); return this; } /** - * Closed gh pull request search builder. + * Mentions gh pull request search builder. * - * @param from - * the closed starting from - * @param to - * the closed ending to + * @param u + * the gh user * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder closed(LocalDate from, LocalDate to) { - String closedRange = from.format(DateTimeFormatter.ISO_DATE) + ".." + to.format(DateTimeFormatter.ISO_DATE); - q("closed", closedRange); + public GHPullRequestSearchBuilder mentions(GHUser u) { + q("mentions", u.getLogin()); return this; } /** - * ClosedAfter gh pull request search builder. + * Is open gh pull request search builder. * - * @param closed - * the closed - * @param inclusive - * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder closedAfter(LocalDate closed, boolean inclusive) { - String comparisonSign = inclusive ? ">=" : ">"; - q("closed:" + comparisonSign + closed.format(DateTimeFormatter.ISO_DATE)); - return this; + public GHPullRequestSearchBuilder isOpen() { + return q("is:open"); } /** - * ClosedBefore gh pull request search builder. + * Is closed gh pull request search builder. * - * @param closed - * the closed - * @param inclusive - * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder closedBefore(LocalDate closed, boolean inclusive) { - String comparisonSign = inclusive ? "<=" : "<"; - q("closed:" + comparisonSign + closed.format(DateTimeFormatter.ISO_DATE)); - return this; + public GHPullRequestSearchBuilder isClosed() { + return q("is:closed"); } /** - * Commit gh pull request search builder. + * Is merged gh pull request search builder. * - * @param sha - * the commit SHA * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder commit(String sha) { - q("SHA", sha); + public GHPullRequestSearchBuilder isMerged() { + return q("is:merged"); + } + + /** + * Is draft gh pull request search builder. + * + * @return the gh pull request search builder + */ + public GHPullRequestSearchBuilder isDraft() { + return q("draft:true"); + } + + /** + * Head gh pull request search builder. + * + * @param branch + * the head branch + * @return the gh pull request search builder + */ + public GHPullRequestSearchBuilder head(GHBranch branch) { + q("head", branch.getName()); return this; } /** - * Created gh pull request search builder. + * Base gh pull request search builder. * - * @param created - * the createdAt + * @param branch + * the base branch * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder created(LocalDate created) { - q("created", created.format(DateTimeFormatter.ISO_DATE)); + public GHPullRequestSearchBuilder base(GHBranch branch) { + q("base", branch.getName()); return this; } /** - * Created gh pull request search builder. + * Commit gh pull request search builder. * - * @param from - * the createdAt starting from - * @param to - * the createdAt ending to + * @param sha + * the commit SHA * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder created(LocalDate from, LocalDate to) { - String createdRange = from.format(DateTimeFormatter.ISO_DATE) + ".." + to.format(DateTimeFormatter.ISO_DATE); - q("created", createdRange); + public GHPullRequestSearchBuilder commit(String sha) { + q("SHA", sha); return this; } /** - * CreatedAfter gh pull request search builder. + * Created gh pull request search builder. * * @param created * the createdAt - * @param inclusive - * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder createdAfter(LocalDate created, boolean inclusive) { - String comparisonSign = inclusive ? ">=" : ">"; - q("created:" + comparisonSign + created.format(DateTimeFormatter.ISO_DATE)); + public GHPullRequestSearchBuilder created(LocalDate created) { + q("created", created.format(DateTimeFormatter.ISO_DATE)); return this; } @@ -210,201 +179,227 @@ public GHPullRequestSearchBuilder createdBefore(LocalDate created, boolean inclu } /** - * CreatedByMe gh pull request search builder. + * CreatedAfter gh pull request search builder. * + * @param created + * the createdAt + * @param inclusive + * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder createdByMe() { - q("author:@me"); + public GHPullRequestSearchBuilder createdAfter(LocalDate created, boolean inclusive) { + String comparisonSign = inclusive ? ">=" : ">"; + q("created:" + comparisonSign + created.format(DateTimeFormatter.ISO_DATE)); return this; } /** - * Head gh pull request search builder. + * Created gh pull request search builder. * - * @param branch - * the head branch + * @param from + * the createdAt starting from + * @param to + * the createdAt ending to * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder head(GHBranch branch) { - q("head", branch.getName()); + public GHPullRequestSearchBuilder created(LocalDate from, LocalDate to) { + String createdRange = from.format(DateTimeFormatter.ISO_DATE) + ".." + to.format(DateTimeFormatter.ISO_DATE); + q("created", createdRange); return this; } /** - * Labels gh pull request search builder. + * Merged gh pull request search builder. * - * @param labels - * the labels + * @param merged + * the merged * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder inLabels(Iterable labels) { - q("label", String.join(",", labels)); + public GHPullRequestSearchBuilder merged(LocalDate merged) { + q("merged", merged.format(DateTimeFormatter.ISO_DATE)); return this; } /** - * Is closed gh pull request search builder. + * MergedBefore gh pull request search builder. * + * @param merged + * the merged + * @param inclusive + * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder isClosed() { - return q("is:closed"); + public GHPullRequestSearchBuilder mergedBefore(LocalDate merged, boolean inclusive) { + String comparisonSign = inclusive ? "<=" : "<"; + q("merged:" + comparisonSign + merged.format(DateTimeFormatter.ISO_DATE)); + return this; } /** - * Is draft gh pull request search builder. + * MergedAfter gh pull request search builder. * + * @param merged + * the merged + * @param inclusive + * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder isDraft() { - return q("draft:true"); + public GHPullRequestSearchBuilder mergedAfter(LocalDate merged, boolean inclusive) { + String comparisonSign = inclusive ? ">=" : ">"; + q("merged:" + comparisonSign + merged.format(DateTimeFormatter.ISO_DATE)); + return this; } /** - * Is merged gh pull request search builder. + * Merged gh pull request search builder. * + * @param from + * the merged starting from + * @param to + * the merged ending to * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder isMerged() { - return q("is:merged"); + public GHPullRequestSearchBuilder merged(LocalDate from, LocalDate to) { + String mergedRange = from.format(DateTimeFormatter.ISO_DATE) + ".." + to.format(DateTimeFormatter.ISO_DATE); + q("merged", mergedRange); + return this; } /** - * Is open gh pull request search builder. + * Closed gh pull request search builder. * + * @param closed + * the closed * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder isOpen() { - return q("is:open"); + public GHPullRequestSearchBuilder closed(LocalDate closed) { + q("closed", closed.format(DateTimeFormatter.ISO_DATE)); + return this; } /** - * Label gh pull request search builder. + * ClosedBefore gh pull request search builder. * - * @param label - * the label + * @param closed + * the closed + * @param inclusive + * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder label(String label) { - q("label", label); + public GHPullRequestSearchBuilder closedBefore(LocalDate closed, boolean inclusive) { + String comparisonSign = inclusive ? "<=" : "<"; + q("closed:" + comparisonSign + closed.format(DateTimeFormatter.ISO_DATE)); return this; } - @Override - public PagedSearchIterable list() { - this.q("is:pr"); - return super.list(); - } - /** - * Mentions gh pull request search builder. + * ClosedAfter gh pull request search builder. * - * @param u - * the gh user + * @param closed + * the closed + * @param inclusive + * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder mentions(GHUser u) { - q("mentions", u.getLogin()); + public GHPullRequestSearchBuilder closedAfter(LocalDate closed, boolean inclusive) { + String comparisonSign = inclusive ? ">=" : ">"; + q("closed:" + comparisonSign + closed.format(DateTimeFormatter.ISO_DATE)); return this; } /** - * Merged gh pull request search builder. + * Closed gh pull request search builder. * - * @param merged - * the merged + * @param from + * the closed starting from + * @param to + * the closed ending to * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder merged(LocalDate merged) { - q("merged", merged.format(DateTimeFormatter.ISO_DATE)); + public GHPullRequestSearchBuilder closed(LocalDate from, LocalDate to) { + String closedRange = from.format(DateTimeFormatter.ISO_DATE) + ".." + to.format(DateTimeFormatter.ISO_DATE); + q("closed", closedRange); return this; } /** - * Merged gh pull request search builder. + * Updated gh pull request search builder. * - * @param from - * the merged starting from - * @param to - * the merged ending to + * @param updated + * the updated * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder merged(LocalDate from, LocalDate to) { - String mergedRange = from.format(DateTimeFormatter.ISO_DATE) + ".." + to.format(DateTimeFormatter.ISO_DATE); - q("merged", mergedRange); + public GHPullRequestSearchBuilder updated(LocalDate updated) { + q("updated", updated.format(DateTimeFormatter.ISO_DATE)); return this; } /** - * MergedAfter gh pull request search builder. + * UpdatedBefore gh pull request search builder. * - * @param merged - * the merged + * @param updated + * the updated * @param inclusive * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder mergedAfter(LocalDate merged, boolean inclusive) { - String comparisonSign = inclusive ? ">=" : ">"; - q("merged:" + comparisonSign + merged.format(DateTimeFormatter.ISO_DATE)); + public GHPullRequestSearchBuilder updatedBefore(LocalDate updated, boolean inclusive) { + String comparisonSign = inclusive ? "<=" : "<"; + q("updated:" + comparisonSign + updated.format(DateTimeFormatter.ISO_DATE)); return this; } /** - * MergedBefore gh pull request search builder. + * UpdatedAfter gh pull request search builder. * - * @param merged - * the merged + * @param updated + * the updated * @param inclusive * whether to include date * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder mergedBefore(LocalDate merged, boolean inclusive) { - String comparisonSign = inclusive ? "<=" : "<"; - q("merged:" + comparisonSign + merged.format(DateTimeFormatter.ISO_DATE)); + public GHPullRequestSearchBuilder updatedAfter(LocalDate updated, boolean inclusive) { + String comparisonSign = inclusive ? ">=" : ">"; + q("updated:" + comparisonSign + updated.format(DateTimeFormatter.ISO_DATE)); return this; } /** - * Order gh pull request search builder. + * Updated gh pull request search builder. * - * @param direction - * the direction + * @param from + * the updated starting from + * @param to + * the updated ending to * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder order(GHDirection direction) { - req.with("order", direction); - return this; - } - - @Override - public GHPullRequestSearchBuilder q(String term) { - super.q(term); + public GHPullRequestSearchBuilder updated(LocalDate from, LocalDate to) { + String updatedRange = from.format(DateTimeFormatter.ISO_DATE) + ".." + to.format(DateTimeFormatter.ISO_DATE); + q("updated", updatedRange); return this; } /** - * Repository gh pull request search builder. + * Label gh pull request search builder. * - * @param repository - * the repository + * @param label + * the label * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder repo(GHRepository repository) { - q("repo", repository.getFullName()); + public GHPullRequestSearchBuilder label(String label) { + q("label", label); return this; } /** - * Sort gh pull request search builder. + * Labels gh pull request search builder. * - * @param sort - * the sort + * @param labels + * the labels * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder sort(GHPullRequestSearchBuilder.Sort sort) { - req.with("sort", sort); + public GHPullRequestSearchBuilder inLabels(Iterable labels) { + q("label", String.join(",", labels)); return this; } @@ -421,64 +416,69 @@ public GHPullRequestSearchBuilder titleLike(String title) { } /** - * Updated gh pull request search builder. + * Order gh pull request search builder. * - * @param updated - * the updated + * @param direction + * the direction * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder updated(LocalDate updated) { - q("updated", updated.format(DateTimeFormatter.ISO_DATE)); + public GHPullRequestSearchBuilder order(GHDirection direction) { + req.with("order", direction); return this; } /** - * Updated gh pull request search builder. + * Sort gh pull request search builder. * - * @param from - * the updated starting from - * @param to - * the updated ending to + * @param sort + * the sort * @return the gh pull request search builder */ - public GHPullRequestSearchBuilder updated(LocalDate from, LocalDate to) { - String updatedRange = from.format(DateTimeFormatter.ISO_DATE) + ".." + to.format(DateTimeFormatter.ISO_DATE); - q("updated", updatedRange); + public GHPullRequestSearchBuilder sort(GHPullRequestSearchBuilder.Sort sort) { + req.with("sort", sort); return this; } - /** - * UpdatedAfter gh pull request search builder. - * - * @param updated - * the updated - * @param inclusive - * whether to include date - * @return the gh pull request search builder - */ - public GHPullRequestSearchBuilder updatedAfter(LocalDate updated, boolean inclusive) { - String comparisonSign = inclusive ? ">=" : ">"; - q("updated:" + comparisonSign + updated.format(DateTimeFormatter.ISO_DATE)); + @Override + public GHPullRequestSearchBuilder q(String term) { + super.q(term); return this; } - /** - * UpdatedBefore gh pull request search builder. - * - * @param updated - * the updated - * @param inclusive - * whether to include date - * @return the gh pull request search builder - */ - public GHPullRequestSearchBuilder updatedBefore(LocalDate updated, boolean inclusive) { - String comparisonSign = inclusive ? "<=" : "<"; - q("updated:" + comparisonSign + updated.format(DateTimeFormatter.ISO_DATE)); - return this; + @Override + public PagedSearchIterable list() { + this.q("is:pr"); + return super.list(); } @Override protected String getApiUrl() { return "/search/issues"; } + + /** + * The sort order values. + */ + public enum Sort { + + /** The comments. */ + COMMENTS, + /** The created. */ + CREATED, + /** The updated. */ + UPDATED, + /** The relevance. */ + RELEVANCE + + } + + private static class PullRequestSearchResult extends SearchResult { + + private GHPullRequest[] items; + + @Override + GHPullRequest[] getItems(GitHub root) { + return items; + } + } } diff --git a/src/main/java/org/kohsuke/github/GHRateLimit.java b/src/main/java/org/kohsuke/github/GHRateLimit.java index 19c5870640..51faa4c10e 100644 --- a/src/main/java/org/kohsuke/github/GHRateLimit.java +++ b/src/main/java/org/kohsuke/github/GHRateLimit.java @@ -8,7 +8,6 @@ import org.kohsuke.github.connector.GitHubConnectorResponse; import java.time.Duration; -import java.time.Instant; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; @@ -31,363 +30,17 @@ @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "JSON API") public class GHRateLimit { - /** - * A rate limit record. - * - * @author Liam Newman - * @since 1.100 - */ - public static class Record { - /** - * EpochSeconds time (UTC) at which this instance was created. - */ - private final long createdAtEpochSeconds = System.currentTimeMillis() / 1000; - - /** - * Allotted API call per time period. - */ - private final int limit; - - /** - * Remaining calls that can be made. - */ - private final int remaining; - - /** - * The time at which the current rate limit window resets in UTC epoch seconds. - */ - private final long resetEpochSeconds; - - /** - * The date at which the rate limit will reset, adjusted to local machine time if the local machine's clock not - * synchronized with to the same clock as the GitHub server. - * - * @see #calculateResetInstant(String) - * @see #getResetInstant() - */ - @Nonnull - private final Instant resetInstant; - - /** - * Instantiates a new Record. - * - * @param limit - * the limit - * @param remaining - * the remaining - * @param resetEpochSeconds - * the reset epoch seconds - */ - public Record(@JsonProperty(value = "limit", required = true) int limit, - @JsonProperty(value = "remaining", required = true) int remaining, - @JsonProperty(value = "reset", required = true) long resetEpochSeconds) { - this(limit, remaining, resetEpochSeconds, null); - } - - /** - * Instantiates a new Record. Called by Jackson data binding or during header parsing. - * - * @param limit - * the limit - * @param remaining - * the remaining - * @param resetEpochSeconds - * the reset epoch seconds - * @param connectorResponse - * the response info - */ - @JsonCreator - Record(@JsonProperty(value = "limit", required = true) int limit, - @JsonProperty(value = "remaining", required = true) int remaining, - @JsonProperty(value = "reset", required = true) long resetEpochSeconds, - @JacksonInject @CheckForNull GitHubConnectorResponse connectorResponse) { - this.limit = limit; - this.remaining = remaining; - this.resetEpochSeconds = resetEpochSeconds; - String updatedAt = null; - if (connectorResponse != null) { - updatedAt = connectorResponse.header("Date"); - } - this.resetInstant = calculateResetInstant(updatedAt); - } - - /** - * Equals. - * - * @param o - * the o - * @return true, if successful - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Record record = (Record) o; - return getRemaining() == record.getRemaining() && getLimit() == record.getLimit() - && getResetEpochSeconds() == record.getResetEpochSeconds() - && getResetInstant().equals(record.getResetInstant()); - } - - /** - * Gets the total number of API calls per hour allotted for this connection. - * - * @return an integer - */ - public int getLimit() { - return limit; - } - - /** - * Gets the remaining number of requests allowed before this connection will be throttled. - * - * @return an integer - */ - public int getRemaining() { - return remaining; - } - - /** - * The date at which the rate limit will reset, adjusted to local machine time if the local machine's clock not - * synchronized with to the same clock as the GitHub server. - * - * If attempting to wait for the rate limit to reset, consider implementing a {@link RateLimitChecker} instead. - * - * @return the calculated date at which the rate limit has or will reset. - * @deprecated Use {@link #getResetInstant()} - */ - @Nonnull - @Deprecated - public Date getResetDate() { - return Date.from(getResetInstant()); - } - - /** - * Gets the time in epoch seconds when the rate limit will reset. - * - * This is the raw value returned by the server. This value is not adjusted if local machine time is not - * synchronized with server time. If attempting to check when the rate limit will reset, use - * {@link #getResetInstant()} or implement a {@link RateLimitChecker} instead. - * - * @return a long representing the time in epoch seconds when the rate limit will reset - * @see #getResetInstant() - */ - public long getResetEpochSeconds() { - return resetEpochSeconds; - } - - /** - * The Instant at which the rate limit will reset, adjusted to local machine time if the local machine's clock - * not synchronized with to the same clock as the GitHub server. - * - * If attempting to wait for the rate limit to reset, consider implementing a {@link RateLimitChecker} instead. - * - * @return the calculated date at which the rate limit has or will reset. - */ - @Nonnull - public Instant getResetInstant() { - return resetInstant; - } - - /** - * Hash code. - * - * @return the int - */ - @Override - public int hashCode() { - return Objects.hash(getRemaining(), getLimit(), getResetEpochSeconds(), getResetInstant()); - } - - /** - * Whether the rate limit reset date indicated by this instance is expired - * - * If attempting to wait for the rate limit to reset, consider implementing a {@link RateLimitChecker} instead. - * - * @return true if the rate limit reset date has passed. Otherwise false. - */ - public boolean isExpired() { - return getResetInstant().toEpochMilli() < System.currentTimeMillis(); - } - - /** - * To string. - * - * @return the string - */ - @Override - public String toString() { - return "{" + "remaining=" + getRemaining() + ", limit=" + getLimit() + ", resetDate=" - + GitHubClient.printInstant(getResetInstant()) + '}'; - } - - /** - * Recalculates the {@link #resetInstant} relative to the local machine clock. - *

- * {@link RateLimitChecker}s and {@link RateLimitHandler}s use {@link #getResetInstant()} to make decisions - * about how long to wait for until for the rate limit to reset. That means that {@link #getResetInstant()} - * needs to be calculated based on the local machine clock. - *

- *

- * When we say that the clock on two machines is "synchronized", we mean that the UTC time returned from - * {@link System#currentTimeMillis()} on each machine is basically the same. For the purposes of rate limits an - * differences of up to a second can be ignored. - *

- *

- * When the clock on the local machine is synchronized to the same time as the clock on the GitHub server (via a - * time service for example), the {@link #resetDate} generated directly from {@link #resetEpochSeconds} will be - * accurate for the local machine as well. - *

- *

- * When the clock on the local machine is not synchronized with the server, the {@link #resetDate} must be - * recalculated relative to the local machine clock. This is done by taking the number of seconds between the - * response "Date" header and {@link #resetEpochSeconds} and then adding that to this record's - * {@link #createdAtEpochSeconds}. - * - * @param updatedAt - * a string date in RFC 1123 - * @return reset date based on the passed date - */ - @Nonnull - private Instant calculateResetInstant(@CheckForNull String updatedAt) { - long updatedAtEpochSeconds = createdAtEpochSeconds; - if (!StringUtils.isBlank(updatedAt)) { - try { - // Get the server date and reset data, will always return a time in GMT - updatedAtEpochSeconds = ZonedDateTime.parse(updatedAt, DateTimeFormatter.RFC_1123_DATE_TIME) - .toEpochSecond(); - } catch (DateTimeParseException e) { - if (LOGGER.isLoggable(FINEST)) { - LOGGER.log(FINEST, "Malformed Date header value " + updatedAt, e); - } - } - } - - // This may seem odd but it results in an accurate or slightly pessimistic reset date - // based on system time rather than assuming the system time synchronized with the server - long calculatedSecondsUntilReset = resetEpochSeconds - updatedAtEpochSeconds; - return Instant.ofEpochMilli((createdAtEpochSeconds + calculatedSecondsUntilReset) * 1000); - } - - /** - * Determine if the current {@link Record} is outdated compared to another. Rate Limit dates are only accurate - * to the second, so we look at other information in the record as well. - * - * {@link Record}s with earlier {@link #getResetEpochSeconds()} are replaced by those with later. - * {@link Record}s with the same {@link #getResetEpochSeconds()} are replaced by those with less remaining - * count. - * - * {@link UnknownLimitRecord}s compare with each other like regular {@link Record}s. - * - * {@link Record}s are replaced by {@link UnknownLimitRecord}s only when the current {@link Record} is expired - * and the {@link UnknownLimitRecord} is not. Otherwise Regular {@link Record}s are not replaced by - * {@link UnknownLimitRecord}s. - * - * Expiration is only considered after other checks, meaning expired records may sometimes be replaced by other - * expired records. - * - * @param other - * the other {@link Record} - * @return the {@link Record} that is most current - */ - Record currentOrUpdated(@Nonnull Record other) { - // This set of checks avoids most calls to isExpired() - // Depends on UnknownLimitRecord.current() to prevent continuous updating of GHRateLimit rateLimit() - if (getResetEpochSeconds() > other.getResetEpochSeconds() - || (getResetEpochSeconds() == other.getResetEpochSeconds() - && getRemaining() <= other.getRemaining())) { - // If the current record has a later reset - // or the current record has the same reset and fewer or same requests remaining - // Then it is most recent - return this; - } else if (!(other instanceof UnknownLimitRecord)) { - // If the above is not the case that means other has a later reset - // or the same reset and fewer requests remaining. - // If the other record is not an unknown record, the other is more recent - return other; - } else if (this.isExpired() && !other.isExpired()) { - // The other is an unknown record. - // If the current record has expired and the other hasn't, return the other. - return other; - } - - // If none of the above, the current record is most valid. - return this; - } - } - - /** - * A limit record used as a placeholder when the actual limit is not known. - * - * @since 1.100 - */ - public static class UnknownLimitRecord extends Record { - - // The default UnknownLimitRecord is an expired record. - private static final UnknownLimitRecord DEFAULT = new UnknownLimitRecord(Long.MIN_VALUE); - - // The starting current UnknownLimitRecord is an expired record. - private static final AtomicReference current = new AtomicReference<>(DEFAULT); - - private static final long defaultUnknownLimitResetSeconds = Duration.ofSeconds(30).getSeconds(); - - /** The Constant unknownLimit. */ - static final int unknownLimit = 1000000; - - /** - * The number of seconds until a {@link UnknownLimitRecord} will expire. - * - * This is set to a somewhat short duration, rather than a long one. This avoids - * {@link GitHubClient#rateLimit(RateLimitTarget)} requesting rate limit updates continuously, but also avoids - * holding on to stale unknown records indefinitely. - * - * When merging {@link GHRateLimit} instances, {@link UnknownLimitRecord}s will be superseded by incoming - * regular {@link Record}s. - * - * @see GHRateLimit#getMergedRateLimit(GHRateLimit) - */ - static long unknownLimitResetSeconds = defaultUnknownLimitResetSeconds; - - /** The Constant unknownRemaining. */ - static final int unknownRemaining = 999999; - - /** - * Current. - * - * @return the record - */ - static Record current() { - Record result = current.get(); - if (result.isExpired()) { - current.set(new UnknownLimitRecord(System.currentTimeMillis() / 1000L + unknownLimitResetSeconds)); - result = current.get(); - } - return result; - } + @Nonnull + private final Record core; - /** - * Reset the current UnknownLimitRecord. For use during testing only. - */ - static void reset() { - current.set(DEFAULT); - unknownLimitResetSeconds = defaultUnknownLimitResetSeconds; - } + @Nonnull + private final Record search; - /** - * Create a new unknown record that resets at the specified time. - * - * @param resetEpochSeconds - * the epoch second time when this record will expire. - */ - private UnknownLimitRecord(long resetEpochSeconds) { - super(unknownLimit, unknownRemaining, resetEpochSeconds); - } - } + @Nonnull + private final Record graphql; - private static final Logger LOGGER = Logger.getLogger(Requester.class.getName()); + @Nonnull + private final Record integrationManifest; /** * The default GHRateLimit provided to new {@link GitHubClient}s. @@ -443,45 +96,139 @@ static GHRateLimit fromRecord(@Nonnull Record record, @Nonnull RateLimitTarget r } } + /** + * Instantiates a new GH rate limit. + * + * @param core + * the core + * @param search + * the search + * @param graphql + * the graphql + * @param integrationManifest + * the integration manifest + */ + @JsonCreator + GHRateLimit(@Nonnull @JsonProperty("core") Record core, + @Nonnull @JsonProperty("search") Record search, + @Nonnull @JsonProperty("graphql") Record graphql, + @Nonnull @JsonProperty("integration_manifest") Record integrationManifest) { + // The Nonnull annotation is ignored by Jackson, we have to check manually + Objects.requireNonNull(core); + Objects.requireNonNull(search); + Objects.requireNonNull(graphql); + Objects.requireNonNull(integrationManifest); + + this.core = core; + this.search = search; + this.graphql = graphql; + this.integrationManifest = integrationManifest; + } + + /** + * Returns the date at which the Core API rate limit will reset. + * + * @return the calculated date at which the rate limit has or will reset. + */ @Nonnull - private final Record core; + public Date getResetDate() { + return getCore().getResetDate(); + } + + /** + * Gets the remaining number of Core APIs requests allowed before this connection will be throttled. + * + * @return an integer + * @since 1.100 + */ + public int getRemaining() { + return getCore().getRemaining(); + } + + /** + * Gets the total number of Core API calls per hour allotted for this connection. + * + * @return an integer + * @since 1.100 + */ + public int getLimit() { + return getCore().getLimit(); + } + + /** + * Gets the time in epoch seconds when the Core API rate limit will reset. + * + * @return a long + * @since 1.100 + */ + public long getResetEpochSeconds() { + return getCore().getResetEpochSeconds(); + } + + /** + * Whether the reset date for the Core API rate limit has passed. + * + * @return true if the rate limit reset date has passed. Otherwise false. + * @since 1.100 + */ + public boolean isExpired() { + return getCore().isExpired(); + } + /** + * The core object provides the rate limit status for all non-search-related resources in the REST API. + * + * @return a rate limit record + * @since 1.100 + */ @Nonnull - private final Record graphql; + public Record getCore() { + return core; + } + /** + * The search record provides the rate limit status for the Search API. + * + * @return a rate limit record + * @since 1.115 + */ + @Nonnull + public Record getSearch() { + return search; + } + + /** + * The graphql record provides the rate limit status for the GraphQL API. + * + * @return a rate limit record + * @since 1.115 + */ @Nonnull - private final Record integrationManifest; + public Record getGraphQL() { + return graphql; + } + /** + * The integration manifest record provides the rate limit status for the GitHub App Manifest code conversion + * endpoint. + * + * @return a rate limit record + * @since 1.115 + */ @Nonnull - private final Record search; + public Record getIntegrationManifest() { + return integrationManifest; + } /** - * Instantiates a new GH rate limit. + * To string. * - * @param core - * the core - * @param search - * the search - * @param graphql - * the graphql - * @param integrationManifest - * the integration manifest + * @return the string */ - @JsonCreator - GHRateLimit(@Nonnull @JsonProperty("core") Record core, - @Nonnull @JsonProperty("search") Record search, - @Nonnull @JsonProperty("graphql") Record graphql, - @Nonnull @JsonProperty("integration_manifest") Record integrationManifest) { - // The Nonnull annotation is ignored by Jackson, we have to check manually - Objects.requireNonNull(core); - Objects.requireNonNull(search); - Objects.requireNonNull(graphql); - Objects.requireNonNull(integrationManifest); - - this.core = core; - this.search = search; - this.graphql = graphql; - this.integrationManifest = integrationManifest; + @Override + public String toString() { + return "GHRateLimit {" + "core " + getCore().toString() + ", search " + getSearch().toString() + ", graphql " + + getGraphQL().toString() + ", integrationManifest " + getIntegrationManifest().toString() + "}"; } /** @@ -506,179 +253,406 @@ && getGraphQL().equals(rateLimit.getGraphQL()) } /** - * The core object provides the rate limit status for all non-search-related resources in the REST API. + * Hash code. * - * @return a rate limit record - * @since 1.100 + * @return the int */ - @Nonnull - public Record getCore() { - return core; + @Override + public int hashCode() { + return Objects.hash(getCore(), getSearch(), getGraphQL(), getIntegrationManifest()); } /** - * The graphql record provides the rate limit status for the GraphQL API. + * Merge a {@link GHRateLimit} with another one to create a new {@link GHRateLimit} keeping the latest + * {@link Record}s from each. * - * @return a rate limit record - * @since 1.115 + * @param newLimit + * {@link GHRateLimit} with potentially updated {@link Record}s. + * @return a merged {@link GHRateLimit} with the latest {@link Record}s from these two instances. If the merged + * instance is equal to the current instance, the current instance is returned. */ @Nonnull - public Record getGraphQL() { - return graphql; + GHRateLimit getMergedRateLimit(@Nonnull GHRateLimit newLimit) { + + GHRateLimit merged = new GHRateLimit(getCore().currentOrUpdated(newLimit.getCore()), + getSearch().currentOrUpdated(newLimit.getSearch()), + getGraphQL().currentOrUpdated(newLimit.getGraphQL()), + getIntegrationManifest().currentOrUpdated(newLimit.getIntegrationManifest())); + + if (merged.equals(this)) { + merged = this; + } + + return merged; } /** - * The integration manifest record provides the rate limit status for the GitHub App Manifest code conversion - * endpoint. + * Gets the specified {@link Record}. * - * @return a rate limit record - * @since 1.115 + * {@link RateLimitTarget#NONE} will return {@link UnknownLimitRecord#DEFAULT} to prevent any clients from + * accidentally waiting on that record to reset before continuing. + * + * @param rateLimitTarget + * the target rate limit record + * @return the target {@link Record} from this instance. */ @Nonnull - public Record getIntegrationManifest() { - return integrationManifest; + Record getRecord(@Nonnull RateLimitTarget rateLimitTarget) { + if (rateLimitTarget == RateLimitTarget.CORE) { + return getCore(); + } else if (rateLimitTarget == RateLimitTarget.SEARCH) { + return getSearch(); + } else if (rateLimitTarget == RateLimitTarget.GRAPHQL) { + return getGraphQL(); + } else if (rateLimitTarget == RateLimitTarget.INTEGRATION_MANIFEST) { + return getIntegrationManifest(); + } else if (rateLimitTarget == RateLimitTarget.NONE) { + return UnknownLimitRecord.DEFAULT; + } else { + throw new IllegalArgumentException("Unknown rate limit target: " + rateLimitTarget.toString()); + } } /** - * Gets the total number of Core API calls per hour allotted for this connection. + * A limit record used as a placeholder when the actual limit is not known. * - * @return an integer * @since 1.100 - * @deprecated use {@link #getCore()} */ - @Deprecated - public int getLimit() { - return getCore().getLimit(); + public static class UnknownLimitRecord extends Record { + + private static final long defaultUnknownLimitResetSeconds = Duration.ofSeconds(30).getSeconds(); + + /** + * The number of seconds until a {@link UnknownLimitRecord} will expire. + * + * This is set to a somewhat short duration, rather than a long one. This avoids + * {@link {@link GitHubClient#rateLimit(RateLimitTarget)}} requesting rate limit updates continuously, but also + * avoids holding on to stale unknown records indefinitely. + * + * When merging {@link GHRateLimit} instances, {@link UnknownLimitRecord}s will be superseded by incoming + * regular {@link Record}s. + * + * @see GHRateLimit#getMergedRateLimit(GHRateLimit) + */ + static long unknownLimitResetSeconds = defaultUnknownLimitResetSeconds; + + /** The Constant unknownLimit. */ + static final int unknownLimit = 1000000; + + /** The Constant unknownRemaining. */ + static final int unknownRemaining = 999999; + + // The default UnknownLimitRecord is an expired record. + private static final UnknownLimitRecord DEFAULT = new UnknownLimitRecord(Long.MIN_VALUE); + + // The starting current UnknownLimitRecord is an expired record. + private static final AtomicReference current = new AtomicReference<>(DEFAULT); + + /** + * Create a new unknown record that resets at the specified time. + * + * @param resetEpochSeconds + * the epoch second time when this record will expire. + */ + private UnknownLimitRecord(long resetEpochSeconds) { + super(unknownLimit, unknownRemaining, resetEpochSeconds); + } + + /** + * Current. + * + * @return the record + */ + static Record current() { + Record result = current.get(); + if (result.isExpired()) { + current.set(new UnknownLimitRecord(System.currentTimeMillis() / 1000L + unknownLimitResetSeconds)); + result = current.get(); + } + return result; + } + + /** + * Reset the current UnknownLimitRecord. For use during testing only. + */ + static void reset() { + current.set(DEFAULT); + unknownLimitResetSeconds = defaultUnknownLimitResetSeconds; + } } /** - * Gets the remaining number of Core APIs requests allowed before this connection will be throttled. + * A rate limit record. * - * @return an integer + * @author Liam Newman * @since 1.100 - * @deprecated use {@link #getCore()} */ - @Deprecated - public int getRemaining() { - return getCore().getRemaining(); - } + public static class Record { + /** + * Remaining calls that can be made. + */ + private final int remaining; + + /** + * Allotted API call per time period. + */ + private final int limit; + + /** + * The time at which the current rate limit window resets in UTC epoch seconds. + */ + private final long resetEpochSeconds; + + /** + * EpochSeconds time (UTC) at which this instance was created. + */ + private final long createdAtEpochSeconds = System.currentTimeMillis() / 1000; + + /** + * The date at which the rate limit will reset, adjusted to local machine time if the local machine's clock not + * synchronized with to the same clock as the GitHub server. + * + * @see #calculateResetDate(String) + * @see #getResetDate() + */ + @Nonnull + private final Date resetDate; + + /** + * Instantiates a new Record. + * + * @param limit + * the limit + * @param remaining + * the remaining + * @param resetEpochSeconds + * the reset epoch seconds + */ + public Record(@JsonProperty(value = "limit", required = true) int limit, + @JsonProperty(value = "remaining", required = true) int remaining, + @JsonProperty(value = "reset", required = true) long resetEpochSeconds) { + this(limit, remaining, resetEpochSeconds, null); + } + + /** + * Instantiates a new Record. Called by Jackson data binding or during header parsing. + * + * @param limit + * the limit + * @param remaining + * the remaining + * @param resetEpochSeconds + * the reset epoch seconds + * @param connectorResponse + * the response info + */ + @JsonCreator + Record(@JsonProperty(value = "limit", required = true) int limit, + @JsonProperty(value = "remaining", required = true) int remaining, + @JsonProperty(value = "reset", required = true) long resetEpochSeconds, + @JacksonInject @CheckForNull GitHubConnectorResponse connectorResponse) { + this.limit = limit; + this.remaining = remaining; + this.resetEpochSeconds = resetEpochSeconds; + String updatedAt = null; + if (connectorResponse != null) { + updatedAt = connectorResponse.header("Date"); + } + this.resetDate = calculateResetDate(updatedAt); + } + + /** + * Determine if the current {@link Record} is outdated compared to another. Rate Limit dates are only accurate + * to the second, so we look at other information in the record as well. + * + * {@link Record}s with earlier {@link #getResetEpochSeconds()} are replaced by those with later. + * {@link Record}s with the same {@link #getResetEpochSeconds()} are replaced by those with less remaining + * count. + * + * {@link UnknownLimitRecord}s compare with each other like regular {@link Record}s. + * + * {@link Record}s are replaced by {@link UnknownLimitRecord}s only when the current {@link Record} is expired + * and the {@link UnknownLimitRecord} is not. Otherwise Regular {@link Record}s are not replaced by + * {@link UnknownLimitRecord}s. + * + * Expiration is only considered after other checks, meaning expired records may sometimes be replaced by other + * expired records. + * + * @param other + * the other {@link Record} + * @return the {@link Record} that is most current + */ + Record currentOrUpdated(@Nonnull Record other) { + // This set of checks avoids most calls to isExpired() + // Depends on UnknownLimitRecord.current() to prevent continuous updating of GHRateLimit rateLimit() + if (getResetEpochSeconds() > other.getResetEpochSeconds() + || (getResetEpochSeconds() == other.getResetEpochSeconds() + && getRemaining() <= other.getRemaining())) { + // If the current record has a later reset + // or the current record has the same reset and fewer or same requests remaining + // Then it is most recent + return this; + } else if (!(other instanceof UnknownLimitRecord)) { + // If the above is not the case that means other has a later reset + // or the same reset and fewer requests remaining. + // If the other record is not an unknown record, the other is more recent + return other; + } else if (this.isExpired() && !other.isExpired()) { + // The other is an unknown record. + // If the current record has expired and the other hasn't, return the other. + return other; + } - /** - * Returns the date at which the Core API rate limit will reset. - * - * @return the calculated date at which the rate limit has or will reset. - * @deprecated use {@link #getCore()} - */ - @Nonnull - @Deprecated - public Date getResetDate() { - return getCore().getResetDate(); - } + // If none of the above, the current record is most valid. + return this; + } - /** - * Gets the time in epoch seconds when the Core API rate limit will reset. - * - * @return a long - * @since 1.100 - * @deprecated use {@link #getCore()} - */ - @Deprecated - public long getResetEpochSeconds() { - return getCore().getResetEpochSeconds(); - } + /** + * Recalculates the {@link #resetDate} relative to the local machine clock. + *

+ * {@link RateLimitChecker}s and {@link RateLimitHandler}s use {@link #getResetDate()} to make decisions about + * how long to wait for until for the rate limit to reset. That means that {@link #getResetDate()} needs to be + * calculated based on the local machine clock. + *

+ *

+ * When we say that the clock on two machines is "synchronized", we mean that the UTC time returned from + * {@link System#currentTimeMillis()} on each machine is basically the same. For the purposes of rate limits an + * differences of up to a second can be ignored. + *

+ *

+ * When the clock on the local machine is synchronized to the same time as the clock on the GitHub server (via a + * time service for example), the {@link #resetDate} generated directly from {@link #resetEpochSeconds} will be + * accurate for the local machine as well. + *

+ *

+ * When the clock on the local machine is not synchronized with the server, the {@link #resetDate} must be + * recalculated relative to the local machine clock. This is done by taking the number of seconds between the + * response "Date" header and {@link #resetEpochSeconds} and then adding that to this record's + * {@link #createdAtEpochSeconds}. + * + * @param updatedAt + * a string date in RFC 1123 + * @return reset date based on the passed date + */ + @Nonnull + private Date calculateResetDate(@CheckForNull String updatedAt) { + long updatedAtEpochSeconds = createdAtEpochSeconds; + if (!StringUtils.isBlank(updatedAt)) { + try { + // Get the server date and reset data, will always return a time in GMT + updatedAtEpochSeconds = ZonedDateTime.parse(updatedAt, DateTimeFormatter.RFC_1123_DATE_TIME) + .toEpochSecond(); + } catch (DateTimeParseException e) { + if (LOGGER.isLoggable(FINEST)) { + LOGGER.log(FINEST, "Malformed Date header value " + updatedAt, e); + } + } + } - /** - * The search record provides the rate limit status for the Search API. - * - * @return a rate limit record - * @since 1.115 - */ - @Nonnull - public Record getSearch() { - return search; - } + // This may seem odd but it results in an accurate or slightly pessimistic reset date + // based on system time rather than assuming the system time synchronized with the server + long calculatedSecondsUntilReset = resetEpochSeconds - updatedAtEpochSeconds; + return new Date((createdAtEpochSeconds + calculatedSecondsUntilReset) * 1000); + } - /** - * Hash code. - * - * @return the int - */ - @Override - public int hashCode() { - return Objects.hash(getCore(), getSearch(), getGraphQL(), getIntegrationManifest()); - } + /** + * Gets the remaining number of requests allowed before this connection will be throttled. + * + * @return an integer + */ + public int getRemaining() { + return remaining; + } - /** - * Whether the reset date for the Core API rate limit has passed. - * - * @return true if the rate limit reset date has passed. Otherwise false. - * @since 1.100 - * @deprecated use {@link #getCore()} - */ - @Deprecated - public boolean isExpired() { - return getCore().isExpired(); - } + /** + * Gets the total number of API calls per hour allotted for this connection. + * + * @return an integer + */ + public int getLimit() { + return limit; + } - /** - * To string. - * - * @return the string - */ - @Override - public String toString() { - return "GHRateLimit {" + "core " + getCore().toString() + ", search " + getSearch().toString() + ", graphql " - + getGraphQL().toString() + ", integrationManifest " + getIntegrationManifest().toString() + "}"; - } + /** + * Gets the time in epoch seconds when the rate limit will reset. + * + * This is the raw value returned by the server. This value is not adjusted if local machine time is not + * synchronized with server time. If attempting to check when the rate limit will reset, use + * {@link #getResetDate()} or implement a {@link RateLimitChecker} instead. + * + * @return a long representing the time in epoch seconds when the rate limit will reset + * @see #getResetDate() + */ + public long getResetEpochSeconds() { + return resetEpochSeconds; + } - /** - * Merge a {@link GHRateLimit} with another one to create a new {@link GHRateLimit} keeping the latest - * {@link Record}s from each. - * - * @param newLimit - * {@link GHRateLimit} with potentially updated {@link Record}s. - * @return a merged {@link GHRateLimit} with the latest {@link Record}s from these two instances. If the merged - * instance is equal to the current instance, the current instance is returned. - */ - @Nonnull - GHRateLimit getMergedRateLimit(@Nonnull GHRateLimit newLimit) { + /** + * Whether the rate limit reset date indicated by this instance is expired + * + * If attempting to wait for the rate limit to reset, consider implementing a {@link RateLimitChecker} instead. + * + * @return true if the rate limit reset date has passed. Otherwise false. + */ + public boolean isExpired() { + return getResetDate().getTime() < System.currentTimeMillis(); + } - GHRateLimit merged = new GHRateLimit(getCore().currentOrUpdated(newLimit.getCore()), - getSearch().currentOrUpdated(newLimit.getSearch()), - getGraphQL().currentOrUpdated(newLimit.getGraphQL()), - getIntegrationManifest().currentOrUpdated(newLimit.getIntegrationManifest())); + /** + * The date at which the rate limit will reset, adjusted to local machine time if the local machine's clock not + * synchronized with to the same clock as the GitHub server. + * + * If attempting to wait for the rate limit to reset, consider implementing a {@link RateLimitChecker} instead. + * + * @return the calculated date at which the rate limit has or will reset. + */ + @Nonnull + public Date getResetDate() { + return new Date(resetDate.getTime()); + } - if (merged.equals(this)) { - merged = this; + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + return "{" + "remaining=" + getRemaining() + ", limit=" + getLimit() + ", resetDate=" + getResetDate() + + '}'; } - return merged; - } + /** + * Equals. + * + * @param o + * the o + * @return true, if successful + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Record record = (Record) o; + return getRemaining() == record.getRemaining() && getLimit() == record.getLimit() + && getResetEpochSeconds() == record.getResetEpochSeconds() + && getResetDate().equals(record.getResetDate()); + } - /** - * Gets the specified {@link Record}. - * - * {@link RateLimitTarget#NONE} will return {@link UnknownLimitRecord#DEFAULT} to prevent any clients from - * accidentally waiting on that record to reset before continuing. - * - * @param rateLimitTarget - * the target rate limit record - * @return the target {@link Record} from this instance. - */ - @Nonnull - Record getRecord(@Nonnull RateLimitTarget rateLimitTarget) { - if (rateLimitTarget == RateLimitTarget.CORE) { - return getCore(); - } else if (rateLimitTarget == RateLimitTarget.SEARCH) { - return getSearch(); - } else if (rateLimitTarget == RateLimitTarget.GRAPHQL) { - return getGraphQL(); - } else if (rateLimitTarget == RateLimitTarget.INTEGRATION_MANIFEST) { - return getIntegrationManifest(); - } else if (rateLimitTarget == RateLimitTarget.NONE) { - return UnknownLimitRecord.DEFAULT; - } else { - throw new IllegalArgumentException("Unknown rate limit target: " + rateLimitTarget.toString()); + /** + * Hash code. + * + * @return the int + */ + @Override + public int hashCode() { + return Objects.hash(getRemaining(), getLimit(), getResetEpochSeconds(), getResetDate()); } } + + private static final Logger LOGGER = Logger.getLogger(Requester.class.getName()); } diff --git a/src/main/java/org/kohsuke/github/GHReaction.java b/src/main/java/org/kohsuke/github/GHReaction.java index 3f16bf41c9..57218b8773 100644 --- a/src/main/java/org/kohsuke/github/GHReaction.java +++ b/src/main/java/org/kohsuke/github/GHReaction.java @@ -11,15 +11,15 @@ */ public class GHReaction extends GHObject { - private ReactionContent content; - - private GHUser user; /** * Create default GHReaction instance */ public GHReaction() { } + private GHUser user; + private ReactionContent content; + /** * The kind of reaction left. * diff --git a/src/main/java/org/kohsuke/github/GHRef.java b/src/main/java/org/kohsuke/github/GHRef.java index 33d54792db..4db5e1c67b 100644 --- a/src/main/java/org/kohsuke/github/GHRef.java +++ b/src/main/java/org/kohsuke/github/GHRef.java @@ -15,48 +15,80 @@ public class GHRef extends GitHubInteractiveObject { /** - * The type GHObject. + * Create default GHRef instance */ - @SuppressFBWarnings( - value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, - justification = "JSON API") - public static class GHObject { + public GHRef() { + } - private String type, sha, url; + private String ref, url; + private GHObject object; - /** - * Create default GHObject instance - */ - public GHObject() { - } + /** + * Name of the ref, such as "refs/tags/abc". + * + * @return the ref + */ + public String getRef() { + return ref; + } - /** - * SHA1 of this object. - * - * @return the sha - */ - public String getSha() { - return sha; - } + /** + * The API URL of this tag, such as https://api.github.com/repos/jenkinsci/jenkins/git/refs/tags/1.312 + * + * @return the url + */ + public URL getUrl() { + return GitHubClient.parseURL(url); + } - /** - * Type of the object, such as "commit". - * - * @return the type - */ - public String getType() { - return type; - } + /** + * The object that this ref points to. + * + * @return the object + */ + public GHObject getObject() { + return object; + } - /** - * API URL to this Git data, such as - * https://api.github.com/repos/jenkinsci/jenkins/git/commits/b72322675eb0114363a9a86e9ad5a170d1d07ac0 - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(url); - } + /** + * Updates this ref to the specified commit. + * + * @param sha + * The SHA1 value to set this reference to + * @throws IOException + * the io exception + */ + public void updateTo(String sha) throws IOException { + updateTo(sha, false); + } + + /** + * Updates this ref to the specified commit. + * + * @param sha + * The SHA1 value to set this reference to + * @param force + * Whether or not to force this ref update. + * @throws IOException + * the io exception + */ + public void updateTo(String sha, Boolean force) throws IOException { + root().createRequest() + .method("PATCH") + .with("sha", sha) + .with("force", force) + .withUrlPath(url) + .fetch(GHRef.class); + } + + /** + * Deletes this ref from the repository using the GitHub API. + * + * @throws IOException + * the io exception + */ + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(url).send(); } /** @@ -104,6 +136,7 @@ static GHRef read(GHRepository repository, String refName) throws IOException { } return result; } + /** * Retrieves all refs of the given type for the current GitHub repository. * @@ -112,8 +145,10 @@ static GHRef read(GHRepository repository, String refName) throws IOException { * @param refType * the type of reg to search for e.g. tags or commits * @return paged iterable of all refs of the specified type + * @throws IOException + * on failure communicating with GitHub, potentially due to an invalid ref type being requested */ - static PagedIterable readMatching(GHRepository repository, String refType) { + static PagedIterable readMatching(GHRepository repository, String refType) throws IOException { if (refType.startsWith("refs/")) { refType = refType.replaceFirst("refs/", ""); } @@ -126,81 +161,48 @@ static PagedIterable readMatching(GHRepository repository, String refType return repository.root().createRequest().withUrlPath(url).toIterable(GHRef[].class, item -> repository.root()); } - private GHObject object; - - private String ref, url; - - /** - * Create default GHRef instance - */ - public GHRef() { - } - /** - * Deletes this ref from the repository using the GitHub API. - * - * @throws IOException - * the io exception + * The type GHObject. */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(url).send(); - } + @SuppressFBWarnings( + value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, + justification = "JSON API") + public static class GHObject { - /** - * The object that this ref points to. - * - * @return the object - */ - public GHObject getObject() { - return object; - } + /** + * Create default GHObject instance + */ + public GHObject() { + } - /** - * Name of the ref, such as "refs/tags/abc". - * - * @return the ref - */ - public String getRef() { - return ref; - } + private String type, sha, url; - /** - * The API URL of this tag, such as https://api.github.com/repos/jenkinsci/jenkins/git/refs/tags/1.312 - * - * @return the url - */ - public URL getUrl() { - return GitHubClient.parseURL(url); - } + /** + * Type of the object, such as "commit". + * + * @return the type + */ + public String getType() { + return type; + } - /** - * Updates this ref to the specified commit. - * - * @param sha - * The SHA1 value to set this reference to - * @throws IOException - * the io exception - */ - public void updateTo(String sha) throws IOException { - updateTo(sha, false); - } + /** + * SHA1 of this object. + * + * @return the sha + */ + public String getSha() { + return sha; + } - /** - * Updates this ref to the specified commit. - * - * @param sha - * The SHA1 value to set this reference to - * @param force - * Whether or not to force this ref update. - * @throws IOException - * the io exception - */ - public void updateTo(String sha, Boolean force) throws IOException { - root().createRequest() - .method("PATCH") - .with("sha", sha) - .with("force", force) - .withUrlPath(url) - .fetch(GHRef.class); + /** + * API URL to this Git data, such as + * https://api.github.com/repos/jenkinsci/jenkins/git/commits/b72322675eb0114363a9a86e9ad5a170d1d07ac0 + * + * @return the url + */ + public URL getUrl() { + return GitHubClient.parseURL(url); + } } } diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index 5c8144aabf..1c6c82851d 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -8,12 +8,11 @@ import java.io.InputStream; import java.net.URL; import java.net.URLEncoder; -import java.time.Instant; import java.util.Collections; import java.util.Date; import java.util.List; -import static java.lang.String.format; +import static java.lang.String.*; // TODO: Auto-generated Javadoc /** @@ -25,62 +24,36 @@ public class GHRelease extends GHObject { /** - * Wrap. - * - * @param releases - * the releases - * @param owner - * the owner - * @return the GH release[] + * Create default GHRelease instance */ - static GHRelease[] wrap(GHRelease[] releases, GHRepository owner) { - for (GHRelease release : releases) { - release.wrap(owner); - } - return releases; + public GHRelease() { } - private List assets; + /** The owner. */ + GHRepository owner; - private String assetsUrl; + private String html_url; + private String assets_url; + private List assets; + private String upload_url; + private String tag_name; + private String target_commitish; + private String name; private String body; - private String discussionUrl; private boolean draft; - private String htmlUrl; - private String name; private boolean prerelease; - private String publishedAt; - private String tagName; - private String tarballUrl; - private String targetCommitish; - private String uploadUrl; - private String zipballUrl; - /** The owner. */ - GHRepository owner; - - /** - * Create default GHRelease instance - */ - public GHRelease() { - } - - /** - * Deletes this release. - * - * @throws IOException - * the io exception - */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(owner.getApiTailUrl("releases/" + getId())).send(); - } + private Date published_at; + private String tarball_url; + private String zipball_url; + private String discussion_url; /** - * Get the cached assets. + * Gets discussion url. Only present if a discussion relating to the release exists * - * @return the assets + * @return the discussion url */ - public List getAssets() { - return Collections.unmodifiableList(assets); + public String getDiscussionUrl() { + return discussion_url; } /** @@ -89,7 +62,7 @@ public List getAssets() { * @return the assets url */ public String getAssetsUrl() { - return assetsUrl; + return assets_url; } /** @@ -102,12 +75,12 @@ public String getBody() { } /** - * Gets discussion url. Only present if a discussion relating to the release exists + * Is draft boolean. * - * @return the discussion url + * @return the boolean */ - public String getDiscussionUrl() { - return discussionUrl; + public boolean isDraft() { + return draft; } /** @@ -116,7 +89,7 @@ public String getDiscussionUrl() { * @return the html url */ public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + return GitHubClient.parseURL(html_url); } /** @@ -128,6 +101,16 @@ public String getName() { return name; } + /** + * Sets name. + * + * @param name + * the name + */ + public void setName(String name) { + this.name = name; + } + /** * Gets owner. * @@ -139,23 +122,21 @@ public GHRepository getOwner() { } /** - * Gets published at. + * Is prerelease boolean. * - * @return the published at + * @return the boolean */ - public Instant getPublishedAt() { - return GitHubClient.parseInstant(publishedAt); + public boolean isPrerelease() { + return prerelease; } /** * Gets published at. * * @return the published at - * @deprecated Use #getPublishedAt() */ - @Deprecated public Date getPublished_at() { - return Date.from(getPublishedAt()); + return new Date(published_at.getTime()); } /** @@ -164,16 +145,7 @@ public Date getPublished_at() { * @return the tag name */ public String getTagName() { - return tagName; - } - - /** - * Gets tarball url. - * - * @return the tarball url - */ - public String getTarballUrl() { - return tarballUrl; + return tag_name; } /** @@ -182,7 +154,7 @@ public String getTarballUrl() { * @return the target commitish */ public String getTargetCommitish() { - return targetCommitish; + return target_commitish; } /** @@ -191,7 +163,7 @@ public String getTargetCommitish() { * @return the upload url */ public String getUploadUrl() { - return uploadUrl; + return upload_url; } /** @@ -200,44 +172,44 @@ public String getUploadUrl() { * @return the zipball url */ public String getZipballUrl() { - return zipballUrl; - } - - /** - * Is draft boolean. - * - * @return the boolean - */ - public boolean isDraft() { - return draft; + return zipball_url; } /** - * Is prerelease boolean. + * Gets tarball url. * - * @return the boolean + * @return the tarball url */ - public boolean isPrerelease() { - return prerelease; + public String getTarballUrl() { + return tarball_url; } /** - * Re-fetch the assets of this release. + * Wrap. * - * @return the assets iterable + * @param owner + * the owner + * @return the GH release */ - public PagedIterable listAssets() { - Requester builder = owner.root().createRequest(); - return builder.withUrlPath(getApiTailUrl("assets")).toIterable(GHAsset[].class, item -> item.wrap(this)); + GHRelease wrap(GHRepository owner) { + this.owner = owner; + return this; } /** - * Updates this release via a builder. + * Wrap. * - * @return the gh release updater + * @param releases + * the releases + * @param owner + * the owner + * @return the GH release[] */ - public GHReleaseUpdater update() { - return new GHReleaseUpdater(this); + static GHRelease[] wrap(GHRelease[] releases, GHRepository owner) { + for (GHRelease release : releases) { + release.wrap(owner); + } + return releases; } /** @@ -288,19 +260,45 @@ public GHAsset uploadAsset(String filename, InputStream stream, String contentTy return builder.contentType(contentType).with(stream).withUrlPath(url).fetch(GHAsset.class).wrap(this); } - private String getApiTailUrl(String end) { - return owner.getApiTailUrl(format("releases/%s/%s", getId(), end)); + /** + * Get the cached assets. + * + * @return the assets + */ + public List getAssets() { + return Collections.unmodifiableList(assets); } /** - * Wrap. + * Re-fetch the assets of this release. * - * @param owner - * the owner - * @return the GH release + * @return the assets iterable */ - GHRelease wrap(GHRepository owner) { - this.owner = owner; - return this; + public PagedIterable listAssets() { + Requester builder = owner.root().createRequest(); + return builder.withUrlPath(getApiTailUrl("assets")).toIterable(GHAsset[].class, item -> item.wrap(this)); + } + + /** + * Deletes this release. + * + * @throws IOException + * the io exception + */ + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(owner.getApiTailUrl("releases/" + getId())).send(); + } + + /** + * Updates this release via a builder. + * + * @return the gh release updater + */ + public GHReleaseUpdater update() { + return new GHReleaseUpdater(this); + } + + private String getApiTailUrl(String end) { + return owner.getApiTailUrl(format("releases/%s/%s", getId(), end)); } } diff --git a/src/main/java/org/kohsuke/github/GHReleaseBuilder.java b/src/main/java/org/kohsuke/github/GHReleaseBuilder.java index 3862aaa1c0..9b2b4a4f0b 100644 --- a/src/main/java/org/kohsuke/github/GHReleaseBuilder.java +++ b/src/main/java/org/kohsuke/github/GHReleaseBuilder.java @@ -12,31 +12,8 @@ * @see GHRepository#createRelease(String) GHRepository#createRelease(String) */ public class GHReleaseBuilder { - /** - * Values for whether this release should be the latest. - */ - public static enum MakeLatest { - - /** Do not make this the latest release */ - FALSE, - /** Latest release is determined by date and higher semantic version */ - LEGACY, - /** Make this the latest release */ - TRUE; - - /** - * To string. - * - * @return the string - */ - @Override - public String toString() { - return name().toLowerCase(Locale.ROOT); - } - } - private final Requester builder; - private final GHRepository repo; + private final Requester builder; /** * Instantiates a new Gh release builder. @@ -65,51 +42,65 @@ public GHReleaseBuilder body(String body) { return this; } + /** + * Specifies the commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. + * + * @param commitish + * Defaults to the repository’s default branch (usually "main"). Unused if the Git tag already exists. + * @return the gh release builder + */ + public GHReleaseBuilder commitish(String commitish) { + builder.with("target_commitish", commitish); + return this; + } + /** * Optional. * - * @param categoryName - * the category of the discussion to be created for the release. Category should already exist + * @param draft + * {@code true} to create a draft (unpublished) release, {@code false} to create a published one. Default + * is {@code false}. * @return the gh release builder */ - public GHReleaseBuilder categoryName(String categoryName) { - builder.with("discussion_category_name", categoryName); + public GHReleaseBuilder draft(boolean draft) { + builder.with("draft", draft); return this; } /** - * Specifies the commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. + * Name gh release builder. * - * @param commitish - * Defaults to the repository’s default branch (usually "main"). Unused if the Git tag already exists. + * @param name + * the name of the release * @return the gh release builder */ - public GHReleaseBuilder commitish(String commitish) { - builder.with("target_commitish", commitish); + public GHReleaseBuilder name(String name) { + builder.with("name", name); return this; } /** - * Create gh release. + * Optional. * - * @return the gh release - * @throws IOException - * the io exception + * @param prerelease + * {@code true} to identify the release as a prerelease. {@code false} to identify the release as a full + * release. Default is {@code false}. + * @return the gh release builder */ - public GHRelease create() throws IOException { - return builder.withUrlPath(repo.getApiTailUrl("releases")).fetch(GHRelease.class).wrap(repo); + public GHReleaseBuilder prerelease(boolean prerelease) { + builder.with("prerelease", prerelease); + return this; } /** * Optional. * - * @param draft - * {@code true} to create a draft (unpublished) release, {@code false} to create a published one. Default - * is {@code false}. + * @param categoryName + * the category of the discussion to be created for the release. Category should already exist * @return the gh release builder */ - public GHReleaseBuilder draft(boolean draft) { - builder.with("draft", draft); + public GHReleaseBuilder categoryName(String categoryName) { + builder.with("discussion_category_name", categoryName); return this; } @@ -126,6 +117,29 @@ public GHReleaseBuilder generateReleaseNotes(boolean generateReleaseNotes) { return this; } + /** + * Values for whether this release should be the latest. + */ + public static enum MakeLatest { + + /** Make this the latest release */ + TRUE, + /** Do not make this the latest release */ + FALSE, + /** Latest release is determined by date and higher semantic version */ + LEGACY; + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + return name().toLowerCase(Locale.ROOT); + } + } + /** * Optional. * @@ -139,27 +153,13 @@ public GHReleaseBuilder makeLatest(MakeLatest latest) { } /** - * Name gh release builder. - * - * @param name - * the name of the release - * @return the gh release builder - */ - public GHReleaseBuilder name(String name) { - builder.with("name", name); - return this; - } - - /** - * Optional. + * Create gh release. * - * @param prerelease - * {@code true} to identify the release as a prerelease. {@code false} to identify the release as a full - * release. Default is {@code false}. - * @return the gh release builder + * @return the gh release + * @throws IOException + * the io exception */ - public GHReleaseBuilder prerelease(boolean prerelease) { - builder.with("prerelease", prerelease); - return this; + public GHRelease create() throws IOException { + return builder.withUrlPath(repo.getApiTailUrl("releases")).fetch(GHRelease.class).wrap(repo); } } diff --git a/src/main/java/org/kohsuke/github/GHReleaseUpdater.java b/src/main/java/org/kohsuke/github/GHReleaseUpdater.java index 13dc07588b..83113412d8 100644 --- a/src/main/java/org/kohsuke/github/GHReleaseUpdater.java +++ b/src/main/java/org/kohsuke/github/GHReleaseUpdater.java @@ -25,26 +25,26 @@ public class GHReleaseUpdater { } /** - * Body gh release updater. + * Tag gh release updater. * - * @param body - * The release notes body. + * @param tag + * the tag * @return the gh release updater */ - public GHReleaseUpdater body(String body) { - builder.with("body", body); + public GHReleaseUpdater tag(String tag) { + builder.with("tag_name", tag); return this; } /** - * Optional. + * Body gh release updater. * - * @param categoryName - * the category of the discussion to be created for the release. Category should already exist - * @return the gh release builder + * @param body + * The release notes body. + * @return the gh release updater */ - public GHReleaseUpdater categoryName(String categoryName) { - builder.with("discussion_category_name", categoryName); + public GHReleaseUpdater body(String body) { + builder.with("body", body); return this; } @@ -73,18 +73,6 @@ public GHReleaseUpdater draft(boolean draft) { return this; } - /** - * Optional. - * - * @param latest - * Whether to make this the latest release. Default is {@code TRUE} - * @return the gh release builder - */ - public GHReleaseUpdater makeLatest(GHReleaseBuilder.MakeLatest latest) { - builder.with("make_latest", latest); - return this; - } - /** * Name gh release updater. * @@ -111,14 +99,26 @@ public GHReleaseUpdater prerelease(boolean prerelease) { } /** - * Tag gh release updater. + * Optional. * - * @param tag - * the tag - * @return the gh release updater + * @param categoryName + * the category of the discussion to be created for the release. Category should already exist + * @return the gh release builder */ - public GHReleaseUpdater tag(String tag) { - builder.with("tag_name", tag); + public GHReleaseUpdater categoryName(String categoryName) { + builder.with("discussion_category_name", categoryName); + return this; + } + + /** + * Optional. + * + * @param latest + * Whether to make this the latest release. Default is {@code TRUE} + * @return the gh release builder + */ + public GHReleaseUpdater makeLatest(GHReleaseBuilder.MakeLatest latest) { + builder.with("make_latest", latest); return this; } diff --git a/src/main/java/org/kohsuke/github/GHRepoHook.java b/src/main/java/org/kohsuke/github/GHRepoHook.java index 18c4c7b6db..e654f591c9 100644 --- a/src/main/java/org/kohsuke/github/GHRepoHook.java +++ b/src/main/java/org/kohsuke/github/GHRepoHook.java @@ -11,13 +11,15 @@ class GHRepoHook extends GHHook { transient GHRepository repository; /** - * Gets the api route. + * Wrap. * - * @return the api route + * @param owner + * the owner + * @return the GH repo hook */ - @Override - String getApiRoute() { - return String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), getId()); + GHRepoHook wrap(GHRepository owner) { + this.repository = owner; + return this; } /** @@ -31,14 +33,12 @@ GitHub root() { } /** - * Wrap. + * Gets the api route. * - * @param owner - * the owner - * @return the GH repo hook + * @return the api route */ - GHRepoHook wrap(GHRepository owner) { - this.repository = owner; - return this; + @Override + String getApiRoute() { + return String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), getId()); } } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 547a663ad8..305dadcf7a 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -24,7 +24,6 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JsonProperty; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -36,9 +35,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.InterruptedIOException; import java.io.Reader; import java.net.URL; -import java.time.Instant; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -71,186 +70,62 @@ public class GHRepository extends GHObject { /** - * Affiliation of a repository collaborator. + * Create default GHRepository instance */ - public enum CollaboratorAffiliation { - - /** The all. */ - ALL, - /** The direct. */ - DIRECT, - /** The outside. */ - OUTSIDE + public GHRepository() { } - /** - * The type Contributor. - */ - public static class Contributor extends GHUser { + private String nodeId, description, homepage, name, full_name; - private int contributions; + private String html_url; // this is the UI - /** - * Create default Contributor instance - */ - public Contributor() { - } + /* + * The license information makes use of the preview API. + * + * See: https://developer.github.com/v3/licenses/ + */ + private GHLicense license; - /** - * Equals. - * - * @param obj - * the obj - * @return true, if successful - */ - @Override - public boolean equals(Object obj) { - // We ignore contributions in the calculation - return super.equals(obj); - } + private String git_url, ssh_url, clone_url, svn_url, mirror_url; - /** - * Gets contributions. - * - * @return the contributions - */ - public int getContributions() { - return contributions; - } + private GHUser owner; // not fully populated. beware. - /** - * Hash code. - * - * @return the int - */ - @Override - public int hashCode() { - // We ignore contributions in the calculation - return super.hashCode(); - } - } + private boolean has_issues, has_wiki, fork, has_downloads, has_pages, archived, disabled, has_projects; - /** - * Sort orders for listing forks. - */ - public enum ForkSort { + private boolean allow_squash_merge; - /** The newest. */ - NEWEST, - /** The oldest. */ - OLDEST, - /** The stargazers. */ - STARGAZERS - } + private boolean allow_merge_commit; - /** - * A {@link GHRepositoryBuilder} that allows multiple properties to be updated per request. - * - * Consumer must call {@link #done()} to commit changes. - */ - @BetaApi - public static class Setter extends GHRepositoryBuilder { + private boolean allow_rebase_merge; - /** - * Instantiates a new setter. - * - * @param repository - * the repository - */ - protected Setter(@Nonnull GHRepository repository) { - super(GHRepository.class, repository.root(), null); - // even when we don't change the name, we need to send it in - // this requirement may be out-of-date, but we do not want to break it - requester.with("name", repository.name); - - requester.method("PATCH").withUrlPath(repository.getApiTailUrl("")); - } - } - - /** - * A {@link GHRepositoryBuilder} that allows multiple properties to be updated per request. - * - * Consumer must call {@link #done()} to commit changes. - */ - @BetaApi - public static class Updater extends GHRepositoryBuilder { + private boolean allow_forking; - /** - * Instantiates a new updater. - * - * @param repository - * the repository - */ - protected Updater(@Nonnull GHRepository repository) { - super(Updater.class, repository.root(), null); - // even when we don't change the name, we need to send it in - // this requirement may be out-of-date, but we do not want to break it - requester.with("name", repository.name); + private boolean delete_branch_on_merge; - requester.method("PATCH").withUrlPath(repository.getApiTailUrl("")); - } - } + @JsonProperty("private") + private boolean _private; - /** - * Visibility of a repository. - */ - public enum Visibility { + private String visibility; - /** The internal. */ - INTERNAL, + private int forks_count, stargazers_count, watchers_count, size, open_issues_count, subscribers_count; - /** The private. */ - PRIVATE, + private String pushed_at; - /** The public. */ - PUBLIC, + private Map milestones = Collections.synchronizedMap(new WeakHashMap<>()); - /** - * Placeholder for unexpected data values. - * - * This avoids throwing exceptions during data binding or reading when the list of allowed values returned from - * GitHub is expanded. - * - * Do not pass this value to any methods. If this value is returned during a request, check the log output and - * report an issue for the missing value. - */ - UNKNOWN; + private String default_branch, language; - /** - * From. - * - * @param value - * the value - * @return the visibility - */ - public static Visibility from(String value) { - return EnumUtils.getNullableEnumOrDefault(Visibility.class, value, Visibility.UNKNOWN); - } + private GHRepository template_repository; - /** - * To string. - * - * @return the string - */ - @Override - public String toString() { - return name().toLowerCase(Locale.ROOT); - } - } + private Map commits = Collections.synchronizedMap(new WeakHashMap<>()); - // Only used within listCodeownersErrors(). - private static class GHCodeownersErrors { - List errors; - } + @SkipFromToString + private GHRepoPermission permissions; - // Only used within listTopics(). - private static class Topics { - List names; - } + private GHRepository source, parent; - static class GHRepoPermission { - boolean pull, push, admin; - } + private Boolean isTemplate; + private boolean compareUsePaginatedCommits; /** * Read. @@ -269,1006 +144,725 @@ static GHRepository read(GitHub root, String owner, String name) throws IOExcept return root.createRequest().withUrlPath("/repos/" + owner + '/' + name).fetch(GHRepository.class); } - private boolean allowForking; - - private boolean allowMergeCommit; - - private boolean allowRebaseMerge; - - private boolean allowSquashMerge; - - private Map commits = Collections.synchronizedMap(new WeakHashMap<>()); - - private boolean compareUsePaginatedCommits; - - private String defaultBranch, language; - - private boolean deleteBranchOnMerge; - - private int forksCount, stargazersCount, watchersCount, size, openIssuesCount, subscribersCount; - - private String gitUrl, sshUrl, cloneUrl, svnUrl, mirrorUrl; - - private boolean hasIssues, hasWiki, fork, hasDownloads, hasPages, archived, disabled, hasProjects; - - private String htmlUrl; // this is the UI - - @JsonProperty("private") - private boolean isPrivate; - private Boolean isTemplate; - - /* - * The license information makes use of the preview API. + /** + * Create deployment gh deployment builder. * - * See: https://developer.github.com/v3/licenses/ + * @param ref + * the ref + * @return the gh deployment builder */ - private GHLicense license; - - private Map milestones = Collections.synchronizedMap(new WeakHashMap<>()); - - private String nodeId, description, homepage, name, fullName; - - private GHUser owner; // not fully populated. beware. - - @SkipFromToString - private GHRepoPermission permissions; - - private String pushedAt; - - private GHRepository source, parent; - - private GHRepository templateRepository; - - private String visibility; + public GHDeploymentBuilder createDeployment(String ref) { + return new GHDeploymentBuilder(this, ref); + } /** - * Create default GHRepository instance + * List deployments paged iterable. + * + * @param sha + * the sha + * @param ref + * the ref + * @param task + * the task + * @param environment + * the environment + * @return the paged iterable */ - public GHRepository() { + public PagedIterable listDeployments(String sha, String ref, String task, String environment) { + return root().createRequest() + .with("sha", sha) + .with("ref", ref) + .with("task", task) + .with("environment", environment) + .withUrlPath(getApiTailUrl("deployments")) + .toIterable(GHDeployment[].class, item -> item.wrap(this)); } /** - * Add collaborators. + * Obtains a single {@link GHDeployment} by its ID. * - * @param users - * the users + * @param id + * the id + * @return the deployment * @throws IOException * the io exception */ - public void addCollaborators(Collection users) throws IOException { - modifyCollaborators(users, "PUT", null); + public GHDeployment getDeployment(long id) throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("deployments/" + id)) + .fetch(GHDeployment.class) + .wrap(this); + } + + static class GHRepoPermission { + boolean pull, push, admin; } /** - * Add collaborators. + * Gets node id. * - * @param users - * the users - * @param permission - * the permission level - * @throws IOException - * the io exception + * @return the node id */ - public void addCollaborators(Collection users, GHOrganization.RepositoryRole permission) - throws IOException { - modifyCollaborators(users, "PUT", permission); + public String getNodeId() { + return nodeId; } /** - * Add collaborators. - * - * @param permission - * the permission level - * @param users - * the users + * Gets description. * - * @throws IOException - * the io exception + * @return the description */ - public void addCollaborators(GHOrganization.RepositoryRole permission, GHUser... users) throws IOException { - addCollaborators(asList(users), permission); + public String getDescription() { + return description; } /** - * Add collaborators. + * Gets homepage. * - * @param users - * the users - * @throws IOException - * the io exception + * @return the homepage */ - public void addCollaborators(GHUser... users) throws IOException { - addCollaborators(asList(users)); + public String getHomepage() { + return homepage; } /** - * Add deploy key gh deploy key. + * Gets the git:// URL to this repository, such as "git://github.com/kohsuke/jenkins.git" This URL is read-only. * - * @param title - * the title - * @param key - * the key - * @return the gh deploy key - * @throws IOException - * the io exception + * @return the git transport url */ - public GHDeployKey addDeployKey(String title, String key) throws IOException { - return addDeployKey(title, key, false); + public String getGitTransportUrl() { + return git_url; } /** - * Add deploy key gh deploy key. + * Gets the HTTPS URL to this repository, such as "https://github.com/kohsuke/jenkins.git" This URL is read-only. * - * @param title - * the title - * @param key - * the key - * @param readOnly - * read-only ability of the key - * @return the gh deploy key - * @throws IOException - * the io exception + * @return the http transport url */ - public GHDeployKey addDeployKey(String title, String key, boolean readOnly) throws IOException { - return root().createRequest() - .method("POST") - .with("title", title) - .with("key", key) - .with("read_only", readOnly) - .withUrlPath(getApiTailUrl("keys")) - .fetch(GHDeployKey.class) - .lateBind(this); + public String getHttpTransportUrl() { + return clone_url; } /** - * Allow private fork. + * Gets the Subversion URL to access this repository: https://github.com/rails/rails * - * @param value - * the value - * @throws IOException - * the io exception + * @return the svn url */ - public void allowForking(boolean value) throws IOException { - set().allowForking(value); + public String getSvnUrl() { + return svn_url; } /** - * Allow merge commit. + * Gets the Mirror URL to access this repository: https://github.com/apache/tomee mirrored from + * git://git.apache.org/tomee.git * - * @param value - * the value - * @throws IOException - * the io exception + * @return the mirror url */ - public void allowMergeCommit(boolean value) throws IOException { - set().allowMergeCommit(value); + public String getMirrorUrl() { + return mirror_url; } /** - * Allow rebase merge. + * Gets the SSH URL to access this repository, such as git@github.com:rails/rails.git * - * @param value - * the value - * @throws IOException - * the io exception + * @return the ssh url */ - public void allowRebaseMerge(boolean value) throws IOException { - set().allowRebaseMerge(value); + public String getSshUrl() { + return ssh_url; } /** - * Allow squash merge. + * Gets the html url. * - * @param value - * the value - * @throws IOException - * the io exception + * @return the html url */ - public void allowSquashMerge(boolean value) throws IOException { - set().allowSquashMerge(value); + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); } /** - * Will archive and this repository as read-only. When a repository is archived, any operation that can change its - * state is forbidden. This applies symmetrically if trying to unarchive it. - * - *

- * When you try to do any operation that modifies a read-only repository, it returns the response: - * - *

-     * org.kohsuke.github.HttpException: {
-     *     "message":"Repository was archived so is read-only.",
-     *     "documentation_url":"https://developer.github.com/v3/repos/#edit"
-     * }
-     * 
+ * Short repository name without the owner. For example 'jenkins' in case of http://github.com/jenkinsci/jenkins * - * @throws IOException - * In case of any networking error or error from the server. + * @return the name */ - public void archive() throws IOException { - set().archive(); - // Generally would not update this record, - // but doing so here since this will result in any other update actions failing - archived = true; + public String getName() { + return name; } /** - * Create an autolink gh autolink builder. + * Full repository name including the owner or organization. For example 'jenkinsci/jenkins' in case of + * http://github.com/jenkinsci/jenkins * - * @return the gh autolink builder + * @return the full name */ - public GHAutolinkBuilder createAutolink() { - return new GHAutolinkBuilder(this); + public String getFullName() { + return full_name; } /** - * Create blob gh blob builder. + * Has pull access boolean. * - * @return the gh blob builder + * @return the boolean */ - public GHBlobBuilder createBlob() { - return new GHBlobBuilder(this); + public boolean hasPullAccess() { + return permissions != null && permissions.pull; } /** - * Creates a check run for a commit. + * Has push access boolean. * - * @param name - * an identifier for the run - * @param headSHA - * the commit hash - * @return a builder which you should customize, then call {@link GHCheckRunBuilder#create} + * @return the boolean */ - public @NonNull GHCheckRunBuilder createCheckRun(@NonNull String name, @NonNull String headSHA) { - return new GHCheckRunBuilder(this, name, headSHA); + public boolean hasPushAccess() { + return permissions != null && permissions.push; } /** - * Create commit gh commit builder. + * Has admin access boolean. * - * @return the gh commit builder + * @return the boolean */ - public GHCommitBuilder createCommit() { - return new GHCommitBuilder(this); + public boolean hasAdminAccess() { + return permissions != null && permissions.admin; } /** - * Create commit status gh commit status. + * Gets the primary programming language. * - * @param sha1 - * the sha 1 - * @param state - * the state - * @param targetUrl - * the target url - * @param description - * the description - * @return the gh commit status - * @throws IOException - * the io exception - * @see #createCommitStatus(String, GHCommitState, String, String, String) #createCommitStatus(String, - * GHCommitState,String,String,String) + * @return the language */ - public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, String targetUrl, String description) - throws IOException { - return createCommitStatus(sha1, state, targetUrl, description, null); + public String getLanguage() { + return language; } /** - * Creates a commit status. + * Gets owner. * - * @param sha1 - * the sha 1 - * @param state - * the state - * @param targetUrl - * Optional parameter that points to the URL that has more details. - * @param description - * Optional short description. - * @param context - * Optional commit status context. - * @return the gh commit status + * @return the owner * @throws IOException * the io exception */ - public GHCommitStatus createCommitStatus(String sha1, - GHCommitState state, - String targetUrl, - String description, - String context) throws IOException { - return root().createRequest() - .method("POST") - .with("state", state) - .with("target_url", targetUrl) - .with("description", description) - .with("context", context) - .withUrlPath(String.format("/repos/%s/%s/statuses/%s", getOwnerName(), this.name, sha1)) - .fetch(GHCommitStatus.class); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getOwner() throws IOException { + return isOffline() ? owner : root().getUser(getOwnerName()); // because 'owner' isn't fully populated } /** - * Creates a new content, or update an existing content. + * Gets issue. * - * @return the gh content builder + * @param id + * the id + * @return the issue + * @throws IOException + * the io exception */ - public GHContentBuilder createContent() { - return new GHContentBuilder(this); + public GHIssue getIssue(int id) throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("issues/" + id)).fetch(GHIssue.class).wrap(this); } /** - * Create deployment gh deployment builder. + * Create issue gh issue builder. * - * @param ref - * the ref - * @return the gh deployment builder + * @param title + * the title + * @return the gh issue builder */ - public GHDeploymentBuilder createDeployment(String ref) { - return new GHDeploymentBuilder(this, ref); + public GHIssueBuilder createIssue(String title) { + return new GHIssueBuilder(this, title); } /** - * Create fork gh repository fork builder. - * (https://docs.github.com/en/rest/repos/forks?apiVersion=2022-11-28#create-a-fork) + * Gets issues. * - * @return the gh repository fork builder + * @param state + * the state + * @return the issues + * @throws IOException + * the io exception */ - public GHRepositoryForkBuilder createFork() { - return new GHRepositoryForkBuilder(this); + public List getIssues(GHIssueState state) throws IOException { + return queryIssues().state(state).list().toList(); } /** - * See https://api.github.com/hooks for possible names and their configuration scheme. TODO: produce type-safe - * binding + * Gets issues. * - * @param name - * Type of the hook to be created. See https://api.github.com/hooks for possible names. - * @param config - * The configuration hash. - * @param events - * Can be null. Types of events to hook into. - * @param active - * the active - * @return the gh hook + * @param state + * the state + * @param milestone + * the milestone + * @return the issues * @throws IOException * the io exception */ - public GHHook createHook(String name, Map config, Collection events, boolean active) - throws IOException { - return GHHooks.repoContext(this, owner).createHook(name, config, events, active); + public List getIssues(GHIssueState state, GHMilestone milestone) throws IOException { + return queryIssues().milestone(milestone == null ? "none" : "" + milestone.getNumber()) + .state(state) + .list() + .toList(); } /** - * Create issue gh issue builder. + * Retrieves issues. * - * @param title - * the title - * @return the gh issue builder + * @return the gh issue query builder */ - public GHIssueBuilder createIssue(String title) { - return new GHIssueBuilder(this, title); + public GHIssueQueryBuilder.ForRepository queryIssues() { + return new GHIssueQueryBuilder.ForRepository(this); } /** - * Create label gh label. + * Create release gh release builder. * - * @param name - * the name - * @param color - * the color - * @return the gh label - * @throws IOException - * the io exception + * @param tag + * the tag + * @return the gh release builder */ - public GHLabel createLabel(String name, String color) throws IOException { - return GHLabel.create(this).name(name).color(color).description("").done(); + public GHReleaseBuilder createRelease(String tag) { + return new GHReleaseBuilder(this, tag); } /** - * Description is still in preview. + * Creates a named ref, such as tag, branch, etc. * * @param name - * the name - * @param color - * the color - * @param description - * the description - * @return gh label - * @throws IOException - * the io exception - */ - public GHLabel createLabel(String name, String color, String description) throws IOException { - return GHLabel.create(this).name(name).color(color).description(description).done(); - } - - /** - * Create milestone gh milestone. - * - * @param title - * the title - * @param description - * the description - * @return the gh milestone + * The name of the fully qualified reference (ie: refs/heads/main). If it doesn't start with 'refs' and + * have at least two slashes, it will be rejected. + * @param sha + * The SHA1 value to set this reference to + * @return the gh ref * @throws IOException * the io exception */ - public GHMilestone createMilestone(String title, String description) throws IOException { + public GHRef createRef(String name, String sha) throws IOException { return root().createRequest() .method("POST") - .with("title", title) - .with("description", description) - .withUrlPath(getApiTailUrl("milestones")) - .fetch(GHMilestone.class) - .lateBind(this); + .with("ref", name) + .with("sha", sha) + .withUrlPath(getApiTailUrl("git/refs")) + .fetch(GHRef.class); } /** - * Create a project for this repository. + * Gets release. * - * @param name - * the name - * @param body - * the body - * @return the gh project + * @param id + * the id + * @return the release * @throws IOException * the io exception */ - public GHProject createProject(String name, String body) throws IOException { - return root().createRequest() - .method("POST") - .with("name", name) - .with("body", body) - .withUrlPath(getApiTailUrl("projects")) - .fetch(GHProject.class) - .lateBind(this); + public GHRelease getRelease(long id) throws IOException { + try { + return root().createRequest() + .withUrlPath(getApiTailUrl("releases/" + id)) + .fetch(GHRelease.class) + .wrap(this); + } catch (FileNotFoundException e) { + return null; // no release for this id + } } /** - * Creates a new pull request. + * Gets release by tag name. * - * @param title - * Required. The title of the pull request. - * @param head - * Required. The name of the branch where your changes are implemented. For cross-repository pull - * requests in the same network, namespace head with a user like this: username:branch. - * @param base - * Required. The name of the branch you want your changes pulled into. This should be an existing branch - * on the current repository. - * @param body - * The contents of the pull request. This is the markdown description of a pull request. - * @return the gh pull request + * @param tag + * the tag + * @return the release by tag name * @throws IOException * the io exception */ - public GHPullRequest createPullRequest(String title, String head, String base, String body) throws IOException { - return createPullRequest(title, head, base, body, true); + public GHRelease getReleaseByTagName(String tag) throws IOException { + try { + return root().createRequest() + .withUrlPath(getApiTailUrl("releases/tags/" + tag)) + .fetch(GHRelease.class) + .wrap(this); + } catch (FileNotFoundException e) { + return null; // no release for this tag + } } /** - * Creates a new pull request. Maintainer's permissions aware. + * Gets latest release. * - * @param title - * Required. The title of the pull request. - * @param head - * Required. The name of the branch where your changes are implemented. For cross-repository pull - * requests in the same network, namespace head with a user like this: username:branch. - * @param base - * Required. The name of the branch you want your changes pulled into. This should be an existing branch - * on the current repository. - * @param body - * The contents of the pull request. This is the markdown description of a pull request. - * @param maintainerCanModify - * Indicates whether maintainers can modify the pull request. - * @return the gh pull request + * @return the latest release * @throws IOException * the io exception */ - public GHPullRequest createPullRequest(String title, - String head, - String base, - String body, - boolean maintainerCanModify) throws IOException { - return createPullRequest(title, head, base, body, maintainerCanModify, false); + public GHRelease getLatestRelease() throws IOException { + try { + return root().createRequest() + .withUrlPath(getApiTailUrl("releases/latest")) + .fetch(GHRelease.class) + .wrap(this); + } catch (FileNotFoundException e) { + return null; // no latest release + } } /** - * Creates a new pull request. Maintainer's permissions and draft aware. + * List releases paged iterable. * - * @param title - * Required. The title of the pull request. - * @param head - * Required. The name of the branch where your changes are implemented. For cross-repository pull - * requests in the same network, namespace head with a user like this: username:branch. - * @param base - * Required. The name of the branch you want your changes pulled into. This should be an existing branch - * on the current repository. - * @param body - * The contents of the pull request. This is the markdown description of a pull request. - * @param maintainerCanModify - * Indicates whether maintainers can modify the pull request. - * @param draft - * Indicates whether to create a draft pull request or not. - * @return the gh pull request + * @return the paged iterable * @throws IOException * the io exception */ - public GHPullRequest createPullRequest(String title, - String head, - String base, - String body, - boolean maintainerCanModify, - boolean draft) throws IOException { + public PagedIterable listReleases() throws IOException { return root().createRequest() - .method("POST") - .with("title", title) - .with("head", head) - .with("base", base) - .with("body", body) - .with("maintainer_can_modify", maintainerCanModify) - .with("draft", draft) - .withUrlPath(getApiTailUrl("pulls")) - .fetch(GHPullRequest.class) - .wrapUp(this); + .withUrlPath(getApiTailUrl("releases")) + .toIterable(GHRelease[].class, item -> item.wrap(this)); } /** - * Creates a named ref, such as tag, branch, etc. + * List tags paged iterable. * - * @param name - * The name of the fully qualified reference (ie: refs/heads/main). If it doesn't start with 'refs' and - * have at least two slashes, it will be rejected. - * @param sha - * The SHA1 value to set this reference to - * @return the gh ref + * @return the paged iterable * @throws IOException * the io exception */ - public GHRef createRef(String name, String sha) throws IOException { + public PagedIterable listTags() throws IOException { return root().createRequest() - .method("POST") - .with("ref", name) - .with("sha", sha) - .withUrlPath(getApiTailUrl("git/refs")) - .fetch(GHRef.class); + .withUrlPath(getApiTailUrl("tags")) + .toIterable(GHTag[].class, item -> item.wrap(this)); } /** - * Create release gh release builder. + * List languages for the specified repository. The value on the right of a language is the number of bytes of code + * written in that language. { "C": 78769, "Python": 7769 } * - * @param tag - * the tag - * @return the gh release builder + * @return the map + * @throws IOException + * the io exception */ - public GHReleaseBuilder createRelease(String tag) { - return new GHReleaseBuilder(this, tag); + public Map listLanguages() throws IOException { + HashMap result = new HashMap<>(); + root().createRequest().withUrlPath(getApiTailUrl("languages")).fetch(HashMap.class).forEach((key, value) -> { + Long addValue = -1L; + if (value instanceof Integer) { + addValue = Long.valueOf((Integer) value); + } + result.put(key.toString(), addValue); + }); + return result; } /** - * Set/Update a repository secret - * "https://docs.github.com/rest/reference/actions#create-or-update-a-repository-secret" + * Gets owner name. * - * @param secretName - * the name of the secret - * @param encryptedValue - * The encrypted value for this secret - * @param publicKeyId - * The id of the Public Key used to encrypt this secret - * @throws IOException - * the io exception + * @return the owner name */ - public void createSecret(String secretName, String encryptedValue, String publicKeyId) throws IOException { - root().createRequest() - .method("PUT") - .with("encrypted_value", encryptedValue) - .with("key_id", publicKeyId) - .withUrlPath(getApiTailUrl("actions/secrets") + "/" + secretName) - .send(); + public String getOwnerName() { + // consistency of the GitHub API is super... some serialized forms of GHRepository populate + // a full GHUser while others populate only the owner and email. This later form is super helpful + // in putting the login in owner.name not owner.login... thankfully we can easily identify this + // second set because owner.login will be null + return owner.login != null ? owner.login : owner.name; } /** - * Create a tag. See https://developer.github.com/v3/git/tags/#create-a-tag-object + * Has issues boolean. * - * @param tag - * The tag's name. - * @param message - * The tag message. - * @param object - * The SHA of the git object this is tagging. - * @param type - * The type of the object we're tagging: "commit", "tree" or "blob". - * @return The newly created tag. - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the boolean */ - public GHTagObject createTag(String tag, String message, String object, String type) throws IOException { - return root().createRequest() - .method("POST") - .with("tag", tag) - .with("message", message) - .with("object", object) - .with("type", type) - .withUrlPath(getApiTailUrl("git/tags")) - .fetch(GHTagObject.class) - .wrap(this); + public boolean hasIssues() { + return has_issues; } /** - * Create tree gh tree builder. + * Has projects boolean. * - * @return the gh tree builder + * @return the boolean */ - public GHTreeBuilder createTree() { - return new GHTreeBuilder(this); + public boolean hasProjects() { + return has_projects; } /** - * Create a repository variable. + * Has wiki boolean. * - * @param name - * the variable name (e.g. test-variable) - * @param value - * the value - * @throws IOException - * the io exception + * @return the boolean */ - public void createVariable(String name, String value) throws IOException { - GHRepositoryVariable.create(this).name(name).value(value).done(); + public boolean hasWiki() { + return has_wiki; } /** - * Create web hook gh hook. + * Is fork boolean. * - * @param url - * the url - * @return the gh hook - * @throws IOException - * the io exception + * @return the boolean */ - public GHHook createWebHook(URL url) throws IOException { - return createWebHook(url, null); + public boolean isFork() { + return fork; } /** - * Create web hook gh hook. + * Is archived boolean. * - * @param url - * the url - * @param events - * the events - * @return the gh hook - * @throws IOException - * the io exception + * @return the boolean */ - public GHHook createWebHook(URL url, Collection events) throws IOException { - return createHook("web", Collections.singletonMap("url", url.toExternalForm()), events, true); + public boolean isArchived() { + return archived; } /** - * Deletes this repository. + * Is disabled boolean. * - * @throws IOException - * the io exception + * @return the boolean */ - public void delete() throws IOException { - try { - root().createRequest().method("DELETE").withUrlPath(getApiTailUrl("")).send(); - } catch (FileNotFoundException x) { - throw (FileNotFoundException) new FileNotFoundException("Failed to delete " + getOwnerName() + "/" + name - + "; might not exist, or you might need the delete_repo scope in your token: http://stackoverflow.com/a/19327004/12916") - .initCause(x); - } + public boolean isDisabled() { + return disabled; } /** - * Delete autolink. - * (https://docs.github.com/en/rest/repos/autolinks?apiVersion=2022-11-28#delete-an-autolink-reference-from-a-repository) + * Is allow squash merge boolean. * - * @param autolinkId - * the autolink id - * @throws IOException - * the io exception + * @return the boolean */ - public void deleteAutolink(int autolinkId) throws IOException { - root().createRequest() - .method("DELETE") - .withHeader("Accept", "application/vnd.github+json") - .withUrlPath(String.format("/repos/%s/%s/autolinks/%d", getOwnerName(), getName(), autolinkId)) - .send(); + public boolean isAllowSquashMerge() { + return allow_squash_merge; } /** - * After pull requests are merged, you can have head branches deleted automatically. + * Is allow merge commit boolean. * - * @param value - * the value - * @throws IOException - * the io exception + * @return the boolean */ - public void deleteBranchOnMerge(boolean value) throws IOException { - set().deleteBranchOnMerge(value); + public boolean isAllowMergeCommit() { + return allow_merge_commit; } /** - * Deletes hook. + * Is allow rebase merge boolean. * - * @param id - * the id - * @throws IOException - * the io exception + * @return the boolean */ - public void deleteHook(int id) throws IOException { - GHHooks.repoContext(this, owner).deleteHook(id); + public boolean isAllowRebaseMerge() { + return allow_rebase_merge; } /** - * Create a repository dispatch event, which can be used to start a workflow/action from outside github, as - * described on https://docs.github.com/en/rest/reference/repos#create-a-repository-dispatch-event + * Is allow private forks * - * @param - * type of client payload - * @param eventType - * the eventType - * @param clientPayload - * a custom payload , can be nullable - * @throws IOException - * the io exception + * @return the boolean */ - public void dispatch(String eventType, @Nullable T clientPayload) throws IOException { - root().createRequest() - .method("POST") - .withUrlPath(getApiTailUrl("dispatches")) - .with("event_type", eventType) - .with("client_payload", clientPayload) - .send(); + public boolean isAllowForking() { + return allow_forking; } /** - * Enable downloads. + * Automatically deleting head branches when pull requests are merged. * - * @param v - * the v - * @throws IOException - * the io exception + * @return the boolean */ - public void enableDownloads(boolean v) throws IOException { - set().downloads(v); + public boolean isDeleteBranchOnMerge() { + return delete_branch_on_merge; } /** - * Enables or disables the issue tracker for this repository. + * Returns the number of all forks of this repository. This not only counts direct forks, but also forks of forks, + * and so on. * - * @param v - * the v - * @throws IOException - * the io exception + * @return the forks */ - public void enableIssueTracker(boolean v) throws IOException { - set().issues(v); + public int getForksCount() { + return forks_count; } /** - * Enables or disables projects for this repository. + * Gets stargazers count. * - * @param v - * the v - * @throws IOException - * the io exception + * @return the stargazers count */ - public void enableProjects(boolean v) throws IOException { - set().projects(v); + public int getStargazersCount() { + return stargazers_count; } /** - * Enables or disables Wiki for this repository. + * Is private boolean. * - * @param v - * the v - * @throws IOException - * the io exception + * @return the boolean */ - public void enableWiki(boolean v) throws IOException { - set().wiki(v); + public boolean isPrivate() { + return _private; } /** - * Equals. + * Visibility of a repository. + */ + public enum Visibility { + + /** The public. */ + PUBLIC, + + /** The internal. */ + INTERNAL, + + /** The private. */ + PRIVATE, + + /** + * Placeholder for unexpected data values. + * + * This avoids throwing exceptions during data binding or reading when the list of allowed values returned from + * GitHub is expanded. + * + * Do not pass this value to any methods. If this value is returned during a request, check the log output and + * report an issue for the missing value. + */ + UNKNOWN; + + /** + * From. + * + * @param value + * the value + * @return the visibility + */ + public static Visibility from(String value) { + return EnumUtils.getNullableEnumOrDefault(Visibility.class, value, Visibility.UNKNOWN); + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + return name().toLowerCase(Locale.ROOT); + } + } + + /** + * Gets the visibility of the repository. * - * @param obj - * the obj - * @return true, if successful + * @return the visibility */ - @Override - public boolean equals(Object obj) { - if (obj instanceof GHRepository) { - GHRepository that = (GHRepository) obj; - return this.getOwnerName().equals(that.getOwnerName()) && this.name.equals(that.name); + public Visibility getVisibility() { + if (visibility == null) { + try { + populate(); + } catch (final IOException e) { + // Convert this to a runtime exception to avoid messy method signature + throw new GHException("Could not populate the visibility of the repository", e); + } } - return false; + return Visibility.from(visibility); } /** - * Forks this repository as your repository. + * Is template boolean. * - * @return Newly forked repository that belong to you. - * @throws IOException - * the io exception - * @deprecated Use {@link #createFork()} + * @return the boolean */ - @Deprecated - public GHRepository fork() throws IOException { - return this.createFork().create(); + public boolean isTemplate() { + if (isTemplate == null) { + try { + populate(); + } catch (IOException e) { + // Convert this to a runtime exception to avoid messy method signature + throw new GHException("Could not populate the template setting of the repository", e); + } + // if this somehow is not populated, set it to false; + isTemplate = Boolean.TRUE.equals(isTemplate); + } + return isTemplate; } /** - * Forks this repository into an organization. + * Has downloads boolean. * - * @param org - * the org - * @return Newly forked repository that belong to you. - * @throws IOException - * the io exception - * @deprecated Use {@link #createFork()} + * @return the boolean */ - @Deprecated - public GHRepository forkTo(GHOrganization org) throws IOException { - return this.createFork().organization(org).create(); + public boolean hasDownloads() { + return has_downloads; } /** - * Gets an artifact by id. + * Has pages boolean. * - * @param id - * the id of the artifact - * @return the artifact - * @throws IOException - * the io exception + * @return the boolean */ - public GHArtifact getArtifact(long id) throws IOException { - return root().createRequest() - .withUrlPath(getApiTailUrl("actions/artifacts"), String.valueOf(id)) - .fetch(GHArtifact.class) - .wrapUp(this); + public boolean hasPages() { + return has_pages; } /** - * Obtains the metadata & the content of a blob. - * - *

- * This method retrieves the whole content in memory, so beware when you are dealing with large BLOB. + * Gets the count of watchers. * - * @param blobSha - * the blob sha - * @return the blob - * @throws IOException - * the io exception - * @see Get a blob - * @see #readBlob(String) #readBlob(String) + * @return the watchers */ - public GHBlob getBlob(String blobSha) throws IOException { - String target = getApiTailUrl("git/blobs/" + blobSha); - return root().createRequest().withUrlPath(target).fetch(GHBlob.class); + public int getWatchersCount() { + return watchers_count; } /** - * Gets branch. + * Gets open issue count. * - * @param name - * the name - * @return the branch - * @throws IOException - * the io exception + * @return the open issue count */ - public GHBranch getBranch(String name) throws IOException { - return root().createRequest().withUrlPath(getApiTailUrl("branches/" + name)).fetch(GHBranch.class).wrap(this); + public int getOpenIssueCount() { + return open_issues_count; } /** - * Gets branches by {@linkplain GHBranch#getName() their names}. + * Gets subscribers count. * - * @return the branches - * @throws IOException - * the io exception + * @return the subscribers count */ - public Map getBranches() throws IOException { - Map r = new TreeMap(); - for (GHBranch p : root().createRequest() - .withUrlPath(getApiTailUrl("branches")) - .toIterable(GHBranch[].class, item -> item.wrap(this)) - .toArray()) { - r.put(p.getName(), p); - } - return r; + public int getSubscribersCount() { + return subscribers_count; } /** - * Gets check runs for given ref. + * Gets pushed at. * - * @param ref - * ref - * @return check runs for given ref - * @see List check runs - * for a specific ref + * @return null if the repository was never pushed at. */ - public PagedIterable getCheckRuns(String ref) { - GitHubRequest request = root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/commits/%s/check-runs", getOwnerName(), name, ref)) - .build(); - return new GHCheckRunsIterable(this, request); + public Date getPushedAt() { + return GitHubClient.parseDate(pushed_at); } /** - * Gets check runs for given ref which validate provided parameters + * Returns the primary branch you'll configure in the "Admin > Options" config page. * - * @param ref - * the Git reference - * @param params - * a map of parameters to filter check runs - * @return check runs for the given ref - * @see List check runs - * for a specific ref + * @return This field is null until the user explicitly configures the default branch. */ - public PagedIterable getCheckRuns(String ref, Map params) { - GitHubRequest request = root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/commits/%s/check-runs", getOwnerName(), name, ref)) - .with(params) - .build(); - return new GHCheckRunsIterable(this, request); + public String getDefaultBranch() { + return default_branch; } /** - * https://developer.github.com/v3/repos/traffic/#clones + * Get Repository template was the repository created from. * - * @return the clone traffic - * @throws IOException - * the io exception + * @return the repository template */ - public GHRepositoryCloneTraffic getCloneTraffic() throws IOException { - return root().createRequest() - .withUrlPath(getApiTailUrl("/traffic/clones")) - .fetch(GHRepositoryCloneTraffic.class); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHRepository getTemplateRepository() { + return (GHRepository) template_repository; } /** - * Gets the names of the collaborators on this repository. This method deviates from the principle of this library - * but it works a lot faster than {@link #getCollaborators()}. + * Gets size. * - * @return the collaborator names - * @throws IOException - * the io exception + * @return the size */ - public Set getCollaboratorNames() throws IOException { - Set r = new HashSet<>(); - // no initializer - we just want to the logins - PagedIterable users = root().createRequest() - .withUrlPath(getApiTailUrl("collaborators")) - .toIterable(GHUser[].class, null); - for (GHUser u : users.toArray()) { - r.add(u.login); - } - return r; + public int getSize() { + return size; } /** - * Gets the names of the collaborators on this repository. This method deviates from the principle of this library - * but it works a lot faster than {@link #getCollaborators()}. - * - * @param affiliation - * Filter users by affiliation - * @return the collaborator names - * @throws IOException - * the io exception + * Affiliation of a repository collaborator. */ - public Set getCollaboratorNames(CollaboratorAffiliation affiliation) throws IOException { - Set r = new HashSet<>(); - // no initializer - we just want to the logins - PagedIterable users = root().createRequest() - .withUrlPath(getApiTailUrl("collaborators")) - .with("affiliation", affiliation) - .toIterable(GHUser[].class, null); - for (GHUser u : users.toArray()) { - r.add(u.login); - } - return r; + public enum CollaboratorAffiliation { + + /** The all. */ + ALL, + /** The direct. */ + DIRECT, + /** The outside. */ + OUTSIDE } /** @@ -1283,864 +877,968 @@ public GHPersonSet getCollaborators() throws IOException { } /** - * Gets a commit object in this repository. + * Lists up the collaborators on this repository. * - * @param sha1 - * the sha 1 - * @return the commit + * @return Users paged iterable * @throws IOException * the io exception */ - public GHCommit getCommit(String sha1) throws IOException { - GHCommit c = commits.get(sha1); - if (c == null) { - c = root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/commits/%s", getOwnerName(), name, sha1)) - .fetch(GHCommit.class) - .wrapUp(this); - commits.put(sha1, c); - } - return c; + public PagedIterable listCollaborators() throws IOException { + return listUsers("collaborators"); } /** - * Gets compare. + * Lists up the collaborators on this repository. * - * @param id1 - * the id 1 - * @param id2 - * the id 2 - * @return the compare + * @param affiliation + * Filter users by affiliation + * @return Users paged iterable * @throws IOException * the io exception */ - public GHCompare getCompare(GHBranch id1, GHBranch id2) throws IOException { - - GHRepository owner1 = id1.getOwner(); - GHRepository owner2 = id2.getOwner(); - - // If the owner of the branches is different, we have a cross-fork compare. - if (owner1 != null && owner2 != null) { - String ownerName1 = owner1.getOwnerName(); - String ownerName2 = owner2.getOwnerName(); - if (!StringUtils.equals(ownerName1, ownerName2)) { - String qualifiedName1 = String.format("%s:%s", ownerName1, id1.getName()); - String qualifiedName2 = String.format("%s:%s", ownerName2, id2.getName()); - return getCompare(qualifiedName1, qualifiedName2); - } - } - - return getCompare(id1.getName(), id2.getName()); + public PagedIterable listCollaborators(CollaboratorAffiliation affiliation) throws IOException { + return listUsers(root().createRequest().with("affiliation", affiliation), "collaborators"); } /** - * Gets compare. + * Lists all + * the + * available assignees to which issues may be assigned. * - * @param id1 - * the id 1 - * @param id2 - * the id 2 - * @return the compare + * @return the paged iterable * @throws IOException * the io exception */ - public GHCompare getCompare(GHCommit id1, GHCommit id2) throws IOException { - return getCompare(id1.getSHA1(), id2.getSHA1()); + public PagedIterable listAssignees() throws IOException { + return listUsers("assignees"); } /** - * Gets a comparison between 2 points in the repository. This would be similar to calling - * git log id1...id2 against a local repository. + * Checks if the given user is an assignee for this repository. * - * @param id1 - * an identifier for the first point to compare from, this can be a sha1 ID (for a commit, tag etc) or a - * direct tag name - * @param id2 - * an identifier for the second point to compare to. Can be the same as the first point. - * @return the comparison output + * @param u + * the u + * @return the boolean * @throws IOException - * on failure communicating with GitHub + * the io exception */ - public GHCompare getCompare(String id1, String id2) throws IOException { - final Requester requester = root().createRequest() - .withUrlPath(getApiTailUrl(String.format("compare/%s...%s", id1, id2))); + public boolean hasAssignee(GHUser u) throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("assignees/" + u.getLogin())).fetchHttpStatusCode() + / 100 == 2; + } - if (compareUsePaginatedCommits) { - requester.with("per_page", 1).with("page", 1); + /** + * Gets the names of the collaborators on this repository. This method deviates from the principle of this library + * but it works a lot faster than {@link #getCollaborators()}. + * + * @return the collaborator names + * @throws IOException + * the io exception + */ + public Set getCollaboratorNames() throws IOException { + Set r = new HashSet<>(); + // no initializer - we just want to the logins + PagedIterable users = root().createRequest() + .withUrlPath(getApiTailUrl("collaborators")) + .toIterable(GHUser[].class, null); + for (GHUser u : users.toArray()) { + r.add(u.login); } - requester.injectMappingValue("GHCompare_usePaginatedCommits", compareUsePaginatedCommits); - GHCompare compare = requester.fetch(GHCompare.class); - return compare.lateBind(this); + return r; } /** - * Returns the primary branch you'll configure in the "Admin > Options" config page. + * Gets the names of the collaborators on this repository. This method deviates from the principle of this library + * but it works a lot faster than {@link #getCollaborators()}. * - * @return This field is null until the user explicitly configures the default branch. + * @param affiliation + * Filter users by affiliation + * @return the collaborator names + * @throws IOException + * the io exception */ - public String getDefaultBranch() { - return defaultBranch; + public Set getCollaboratorNames(CollaboratorAffiliation affiliation) throws IOException { + Set r = new HashSet<>(); + // no initializer - we just want to the logins + PagedIterable users = root().createRequest() + .withUrlPath(getApiTailUrl("collaborators")) + .with("affiliation", affiliation) + .toIterable(GHUser[].class, null); + for (GHUser u : users.toArray()) { + r.add(u.login); + } + return r; } /** - * Gets deploy keys. + * Checks if the given user is a collaborator for this repository. * - * @return the deploy keys + * @param user + * a {@link GHUser} + * @return true if the user is a collaborator for this repository * @throws IOException * the io exception */ - public List getDeployKeys() throws IOException { + public boolean isCollaborator(GHUser user) throws IOException { return root().createRequest() - .withUrlPath(getApiTailUrl("keys")) - .toIterable(GHDeployKey[].class, item -> item.lateBind(this)) - .toList(); + .withUrlPath(getApiTailUrl("collaborators/" + user.getLogin())) + .fetchHttpStatusCode() == 204; } /** - * Obtains a single {@link GHDeployment} by its ID. + * Obtain permission for a given user in this repository. * - * @param id - * the id - * @return the deployment + * @param user + * a {@link GHUser#getLogin} + * @return the permission * @throws IOException * the io exception */ - public GHDeployment getDeployment(long id) throws IOException { - return root().createRequest() - .withUrlPath(getApiTailUrl("deployments/" + id)) - .fetch(GHDeployment.class) - .wrap(this); + public GHPermissionType getPermission(String user) throws IOException { + GHPermission perm = root().createRequest() + .withUrlPath(getApiTailUrl("collaborators/" + user + "/permission")) + .fetch(GHPermission.class); + return perm.getPermissionType(); } /** - * Gets description. + * Obtain permission for a given user in this repository. * - * @return the description + * @param u + * the user + * @return the permission + * @throws IOException + * the io exception */ - public String getDescription() { - return description; + public GHPermissionType getPermission(GHUser u) throws IOException { + return getPermission(u.getLogin()); } /** - * Gets directory content. + * Check if a user has at least the given permission in this repository. * - * @param path - * the path - * @return the directory content + * @param user + * a {@link GHUser#getLogin} + * @param permission + * the permission to check + * @return true if the user has at least this permission level * @throws IOException * the io exception */ - public List getDirectoryContent(String path) throws IOException { - return getDirectoryContent(path, null); + public boolean hasPermission(String user, GHPermissionType permission) throws IOException { + return getPermission(user).implies(permission); } /** - * Gets directory content. + * Check if a user has at least the given permission in this repository. * - * @param path - * the path - * @param ref - * the ref - * @return the directory content + * @param user + * the user + * @param permission + * the permission to check + * @return true if the user has at least this permission level * @throws IOException * the io exception */ - public List getDirectoryContent(String path, String ref) throws IOException { - Requester requester = root().createRequest(); - while (path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - String target = getApiTailUrl("contents/" + path); - - return requester.with("ref", ref) - .withUrlPath(target) - .toIterable(GHContent[].class, item -> item.wrap(this)) - .toList(); + public boolean hasPermission(GHUser user, GHPermissionType permission) throws IOException { + return hasPermission(user.getLogin(), permission); } /** - * Gets file content. + * If this repository belongs to an organization, return a set of teams. * - * @param path - * the path - * @return the file content + * @return the teams * @throws IOException * the io exception */ - public GHContent getFileContent(String path) throws IOException { - return getFileContent(path, null); + public Set getTeams() throws IOException { + GHOrganization org = root().getOrganization(getOwnerName()); + return root().createRequest() + .withUrlPath(getApiTailUrl("teams")) + .toIterable(GHTeam[].class, item -> item.wrapUp(org)) + .toSet(); } /** - * Gets file content. + * Add collaborators. + * + * @param permission + * the permission level + * @param users + * the users * - * @param path - * the path - * @param ref - * the ref - * @return the file content * @throws IOException * the io exception */ - public GHContent getFileContent(String path, String ref) throws IOException { - Requester requester = root().createRequest(); - String target = getApiTailUrl("contents/" + path); - - return requester.with("ref", ref).withUrlPath(target).fetch(GHContent.class).wrap(this); + public void addCollaborators(GHOrganization.RepositoryRole permission, GHUser... users) throws IOException { + addCollaborators(asList(users), permission); } /** - * Returns the number of all forks of this repository. This not only counts direct forks, but also forks of forks, - * and so on. + * Add collaborators. * - * @return the forks + * @param users + * the users + * @throws IOException + * the io exception */ - public int getForksCount() { - return forksCount; + public void addCollaborators(GHUser... users) throws IOException { + addCollaborators(asList(users)); } /** - * Full repository name including the owner or organization. For example 'jenkinsci/jenkins' in case of - * http://github.com/jenkinsci/jenkins + * Add collaborators. * - * @return the full name + * @param users + * the users + * @throws IOException + * the io exception */ - public String getFullName() { - return fullName; + public void addCollaborators(Collection users) throws IOException { + modifyCollaborators(users, "PUT", null); } /** - * Gets the git:// URL to this repository, such as "git://github.com/kohsuke/jenkins.git" This URL is read-only. + * Add collaborators. * - * @return the git transport url + * @param users + * the users + * @param permission + * the permission level + * @throws IOException + * the io exception */ - public String getGitTransportUrl() { - return gitUrl; + public void addCollaborators(Collection users, GHOrganization.RepositoryRole permission) + throws IOException { + modifyCollaborators(users, "PUT", permission); } /** - * Gets homepage. + * Remove collaborators. * - * @return the homepage + * @param users + * the users + * @throws IOException + * the io exception */ - public String getHomepage() { - return homepage; + public void removeCollaborators(GHUser... users) throws IOException { + removeCollaborators(asList(users)); } /** - * Gets hook. + * Remove collaborators. * - * @param id - * the id - * @return the hook + * @param users + * the users * @throws IOException * the io exception */ - public GHHook getHook(int id) throws IOException { - return GHHooks.repoContext(this, owner).getHook(id); + public void removeCollaborators(Collection users) throws IOException { + modifyCollaborators(users, "DELETE", null); + } + + private void modifyCollaborators(@NonNull Collection users, + @NonNull String method, + @CheckForNull GHOrganization.RepositoryRole permission) throws IOException { + Requester requester = root().createRequest().method(method); + if (permission != null) { + requester = requester.with("permission", permission.toString()).inBody(); + } + + // Make sure that the users collection doesn't have any duplicates + for (GHUser user : new LinkedHashSet<>(users)) { + requester.withUrlPath(getApiTailUrl("collaborators/" + user.getLogin())).send(); + } } /** - * Retrieves the currently configured hooks. + * Sets email service hook. * - * @return the hooks + * @param address + * the address * @throws IOException * the io exception */ - public List getHooks() throws IOException { - return GHHooks.repoContext(this, owner).getHooks(); + public void setEmailServiceHook(String address) throws IOException { + Map config = new HashMap<>(); + config.put("address", address); + root().createRequest() + .method("POST") + .with("name", "email") + .with("config", config) + .with("active", true) + .withUrlPath(getApiTailUrl("hooks")) + .send(); } /** - * Gets the html url. + * Enables or disables the issue tracker for this repository. * - * @return the html url + * @param v + * the v + * @throws IOException + * the io exception */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public void enableIssueTracker(boolean v) throws IOException { + set().issues(v); } /** - * Gets the HTTPS URL to this repository, such as "https://github.com/kohsuke/jenkins.git" This URL is read-only. + * Enables or disables projects for this repository. * - * @return the http transport url + * @param v + * the v + * @throws IOException + * the io exception */ - public String getHttpTransportUrl() { - return cloneUrl; + public void enableProjects(boolean v) throws IOException { + set().projects(v); } /** - * Gets issue. + * Enables or disables Wiki for this repository. * - * @param number - * the number of the issue - * @return the issue + * @param v + * the v * @throws IOException * the io exception */ - public GHIssue getIssue(int number) throws IOException { - return root().createRequest().withUrlPath(getApiTailUrl("issues/" + number)).fetch(GHIssue.class).wrap(this); + public void enableWiki(boolean v) throws IOException { + set().wiki(v); } /** - * Get a single issue event. See https://developer.github.com/v3/issues/events/#get-a-single-event + * Enable downloads. * - * @param id - * the id - * @return the issue event + * @param v + * the v * @throws IOException * the io exception */ - public GHIssueEvent getIssueEvent(long id) throws IOException { - return root().createRequest().withUrlPath(getApiTailUrl("issues/events/" + id)).fetch(GHIssueEvent.class); + public void enableDownloads(boolean v) throws IOException { + set().downloads(v); } /** - * Gets issues. + * Rename this repository. * - * @param state - * the state - * @return the issues + * @param name + * the name * @throws IOException * the io exception */ - public List getIssues(GHIssueState state) throws IOException { - return queryIssues().state(state).list().toList(); + public void renameTo(String name) throws IOException { + set().name(name); } /** - * Gets issues. + * Sets description. * - * @param state - * the state - * @param milestone - * the milestone - * @return the issues + * @param value + * the value * @throws IOException * the io exception */ - public List getIssues(GHIssueState state, GHMilestone milestone) throws IOException { - return queryIssues().milestone(milestone == null ? "none" : "" + milestone.getNumber()) - .state(state) - .list() - .toList(); + public void setDescription(String value) throws IOException { + set().description(value); } /** - * Gets label. + * Sets homepage. * - * @param name - * the name - * @return the label + * @param value + * the value * @throws IOException * the io exception */ - public GHLabel getLabel(String name) throws IOException { - return GHLabel.read(this, name); + public void setHomepage(String value) throws IOException { + set().homepage(value); } /** - * Gets the primary programming language. + * Sets default branch. * - * @return the language + * @param value + * the value + * @throws IOException + * the io exception */ - public String getLanguage() { - return language; + public void setDefaultBranch(String value) throws IOException { + set().defaultBranch(value); } /** - * Gets the last status of this commit, which is what gets shown in the UI. + * Sets private. * - * @param sha1 - * the sha 1 - * @return the last commit status + * @param value + * the value * @throws IOException * the io exception */ - public GHCommitStatus getLastCommitStatus(String sha1) throws IOException { - List v = listCommitStatuses(sha1).toList(); - return v.isEmpty() ? null : v.get(0); + public void setPrivate(boolean value) throws IOException { + set().private_(value); } /** - * Gets latest release. + * Sets visibility. * - * @return the latest release + * @param value + * the value * @throws IOException * the io exception */ - public GHRelease getLatestRelease() throws IOException { - try { - return root().createRequest() - .withUrlPath(getApiTailUrl("releases/latest")) - .fetch(GHRelease.class) - .wrap(this); - } catch (FileNotFoundException e) { - return null; // no latest release - } + public void setVisibility(final Visibility value) throws IOException { + root().createRequest() + .method("PATCH") + .with("name", name) + .with("visibility", value) + .withUrlPath(getApiTailUrl("")) + .send(); } /** - * Gets the basic license details for the repository. + * Allow squash merge. * - * @return null if there's no license. + * @param value + * the value * @throws IOException - * as usual but also if you don't use the preview connector + * the io exception */ - public GHLicense getLicense() throws IOException { - GHContentWithLicense lic = getLicenseContent_(); - return lic != null ? lic.license : null; + public void allowSquashMerge(boolean value) throws IOException { + set().allowSquashMerge(value); } /** - * Retrieves the contents of the repository's license file - makes an additional API call. + * Allow merge commit. * - * @return details regarding the license contents, or null if there's no license. + * @param value + * the value * @throws IOException - * as usual but also if you don't use the preview connector + * the io exception */ - public GHContent getLicenseContent() throws IOException { - return getLicenseContent_(); + public void allowMergeCommit(boolean value) throws IOException { + set().allowMergeCommit(value); } /** - * Gets milestone. + * Allow rebase merge. * - * @param number - * the number - * @return the milestone + * @param value + * the value * @throws IOException * the io exception */ - public GHMilestone getMilestone(int number) throws IOException { - GHMilestone m = milestones.get(number); - if (m == null) { - m = root().createRequest().withUrlPath(getApiTailUrl("milestones/" + number)).fetch(GHMilestone.class); - m.owner = this; - milestones.put(m.getNumber(), m); - } - return m; + public void allowRebaseMerge(boolean value) throws IOException { + set().allowRebaseMerge(value); } /** - * Gets the Mirror URL to access this repository: https://github.com/apache/tomee mirrored from - * git://git.apache.org/tomee.git + * Allow private fork. * - * @return the mirror url + * @param value + * the value + * @throws IOException + * the io exception */ - public String getMirrorUrl() { - return mirrorUrl; + public void allowForking(boolean value) throws IOException { + set().allowForking(value); } /** - * Short repository name without the owner. For example 'jenkins' in case of http://github.com/jenkinsci/jenkins + * After pull requests are merged, you can have head branches deleted automatically. * - * @return the name + * @param value + * the value + * @throws IOException + * the io exception */ - public String getName() { - return name; + public void deleteBranchOnMerge(boolean value) throws IOException { + set().deleteBranchOnMerge(value); } /** - * Gets node id. + * Deletes this repository. * - * @return the node id + * @throws IOException + * the io exception */ - public String getNodeId() { - return nodeId; + public void delete() throws IOException { + try { + root().createRequest().method("DELETE").withUrlPath(getApiTailUrl("")).send(); + } catch (FileNotFoundException x) { + throw (FileNotFoundException) new FileNotFoundException("Failed to delete " + getOwnerName() + "/" + name + + "; might not exist, or you might need the delete_repo scope in your token: http://stackoverflow.com/a/19327004/12916") + .initCause(x); + } } /** - * Gets open issue count. + * Will archive and this repository as read-only. When a repository is archived, any operation that can change its + * state is forbidden. This applies symmetrically if trying to unarchive it. * - * @return the open issue count + *

+ * When you try to do any operation that modifies a read-only repository, it returns the response: + * + *

+     * org.kohsuke.github.HttpException: {
+     *     "message":"Repository was archived so is read-only.",
+     *     "documentation_url":"https://developer.github.com/v3/repos/#edit"
+     * }
+     * 
+ * + * @throws IOException + * In case of any networking error or error from the server. */ - public int getOpenIssueCount() { - return openIssuesCount; + public void archive() throws IOException { + set().archive(); + // Generally would not update this record, + // but doing so here since this will result in any other update actions failing + archived = true; } /** - * Gets owner. + * Creates a builder that can be used to bulk update repository settings. * - * @return the owner - * @throws IOException - * the io exception + * @return the repository updater */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getOwner() throws IOException { - return isOffline() ? owner : root().getUser(getOwnerName()); // because 'owner' isn't fully populated + public Updater update() { + return new Updater(this); } /** - * Gets owner name. + * Creates a builder that can be used to bulk update repository settings. * - * @return the owner name + * @return the repository updater */ - public String getOwnerName() { - // consistency of the GitHub API is super... some serialized forms of GHRepository populate - // a full GHUser while others populate only the owner and email. This later form is super helpful - // in putting the login in owner.name not owner.login... thankfully we can easily identify this - // second set because owner.login will be null - return owner.login != null ? owner.login : owner.name; + public Setter set() { + return new Setter(this); } /** - * Forked repositories have a 'parent' attribute that specifies the repository this repository is directly forked - * from. If we keep traversing {@link #getParent()} until it returns null, that is {@link #getSource()}. - * - * @return {@link GHRepository} that points to the repository where this repository is forked directly from. - * Otherwise null. - * @throws IOException - * the io exception - * @see #getSource() #getSource() + * Sort orders for listing forks. */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getParent() throws IOException { - if (fork && parent == null) { - populate(); - } + public enum ForkSort { - if (parent == null) { - return null; - } - return parent; + /** The newest. */ + NEWEST, + /** The oldest. */ + OLDEST, + /** The stargazers. */ + STARGAZERS } /** - * Obtain permission for a given user in this repository. + * Lists all the direct forks of this repository, sorted by github api default, currently {@link ForkSort#NEWEST + * ForkSort.NEWEST}*. * - * @param u - * the user - * @return the permission - * @throws IOException - * the io exception - */ - public GHPermissionType getPermission(GHUser u) throws IOException { - return getPermission(u.getLogin()); + * @return the paged iterable + */ + public PagedIterable listForks() { + return listForks(null); } /** - * Obtain permission for a given user in this repository. + * Lists all the direct forks of this repository, sorted by the given sort order. * - * @param user - * a {@link GHUser#getLogin} - * @return the permission - * @throws IOException - * the io exception + * @param sort + * the sort order. If null, defaults to github api default, currently {@link ForkSort#NEWEST + * ForkSort.NEWEST}. + * @return the paged iterable */ - public GHPermissionType getPermission(String user) throws IOException { - GHPermission perm = root().createRequest() - .withUrlPath(getApiTailUrl("collaborators/" + user + "/permission")) - .fetch(GHPermission.class); - return perm.getPermissionType(); + public PagedIterable listForks(final ForkSort sort) { + return root().createRequest() + .with("sort", sort) + .withUrlPath(getApiTailUrl("forks")) + .toIterable(GHRepository[].class, null); } /** - * Gets the public key for the given repo. + * Forks this repository as your repository. * - * @return the public key + * @return Newly forked repository that belong to you. * @throws IOException * the io exception */ - public GHRepositoryPublicKey getPublicKey() throws IOException { - return root().createRequest() - .withUrlPath(getApiTailUrl("/actions/secrets/public-key")) - .fetch(GHRepositoryPublicKey.class) - .wrapUp(this); + public GHRepository fork() throws IOException { + root().createRequest().method("POST").withUrlPath(getApiTailUrl("forks")).send(); + + // this API is asynchronous. we need to wait for a bit + for (int i = 0; i < 10; i++) { + GHRepository r = root().getMyself().getRepository(name); + if (r != null) { + return r; + } + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw (IOException) new InterruptedIOException().initCause(e); + } + } + throw new IOException(this + " was forked but can't find the new repository"); } /** - * Retrieves a specified pull request. + * Sync this repository fork branch * - * @param number - * the number of the pull request - * @return the pull request + * @param branch + * the branch to sync + * @return The current repository * @throws IOException * the io exception */ - public GHPullRequest getPullRequest(int number) throws IOException { + public GHBranchSync sync(String branch) throws IOException { return root().createRequest() - .withUrlPath(getApiTailUrl("pulls/" + number)) - .fetch(GHPullRequest.class) - .wrapUp(this); + .method("POST") + .with("branch", branch) + .withUrlPath(getApiTailUrl("merge-upstream")) + .fetch(GHBranchSync.class) + .wrap(this); } /** - * Retrieves all the pull requests of a particular state. + * Forks this repository into an organization. * - * @param state - * the state - * @return the pull requests + * @param org + * the org + * @return Newly forked repository that belong to you. * @throws IOException * the io exception - * @deprecated Use {@link #queryPullRequests()} */ - @Deprecated - public List getPullRequests(GHIssueState state) throws IOException { - return queryPullRequests().state(state).list().toList(); - } + public GHRepository forkTo(GHOrganization org) throws IOException { + root().createRequest() + .method("POST") + .with("organization", org.getLogin()) + .withUrlPath(getApiTailUrl("forks")) + .send(); - /** - * Gets pushed at. - * - * @return null if the repository was never pushed at. - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getPushedAt() { - return GitHubClient.parseInstant(pushedAt); + // this API is asynchronous. we need to wait for a bit + for (int i = 0; i < 10; i++) { + GHRepository r = org.getRepository(name); + if (r != null) { + return r; + } + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + throw (IOException) new InterruptedIOException().initCause(e); + } + } + throw new IOException(this + " was forked into " + org.getLogin() + " but can't find the new repository"); } /** - * https://developer.github.com/v3/repos/contents/#get-the-readme + * Retrieves a specified pull request. * - * @return the readme + * @param i + * the + * @return the pull request * @throws IOException * the io exception */ - public GHContent getReadme() throws IOException { - Requester requester = root().createRequest(); - return requester.withUrlPath(getApiTailUrl("readme")).fetch(GHContent.class).wrap(this); + public GHPullRequest getPullRequest(int i) throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("pulls/" + i)).fetch(GHPullRequest.class).wrapUp(this); } /** - * Retrieve a ref of the given type for the current GitHub repository. + * Retrieves pull requests. * - * @param refName - * eg: heads/branch - * @return refs matching the request type - * @throws IOException - * on failure communicating with GitHub, potentially due to an invalid ref type being requested + * @return the gh pull request query builder */ - public GHRef getRef(String refName) throws IOException { - return GHRef.read(this, refName); + public GHPullRequestQueryBuilder queryPullRequests() { + return new GHPullRequestQueryBuilder(this); } /** - * Retrieves all refs for the github repository. + * Retrieves pull requests according to search terms. * - * @return an array of GHRef elements corresponding with the refs in the remote repository. - * @throws IOException - * on failure communicating with GitHub + * @return gh pull request search builder for current repository */ - public GHRef[] getRefs() throws IOException { - return listRefs().toArray(); + public GHPullRequestSearchBuilder searchPullRequests() { + return new GHPullRequestSearchBuilder(this.root()).repo(this); } /** - * Retrieves all refs of the given type for the current GitHub repository. + * Creates a new pull request. * - * @param refType - * the type of reg to search for e.g. tags or commits - * @return an array of all refs matching the request type + * @param title + * Required. The title of the pull request. + * @param head + * Required. The name of the branch where your changes are implemented. For cross-repository pull + * requests in the same network, namespace head with a user like this: username:branch. + * @param base + * Required. The name of the branch you want your changes pulled into. This should be an existing branch + * on the current repository. + * @param body + * The contents of the pull request. This is the markdown description of a pull request. + * @return the gh pull request * @throws IOException - * on failure communicating with GitHub, potentially due to an invalid ref type being requested + * the io exception */ - public GHRef[] getRefs(String refType) throws IOException { - return listRefs(refType).toArray(); + public GHPullRequest createPullRequest(String title, String head, String base, String body) throws IOException { + return createPullRequest(title, head, base, body, true); } /** - * Gets release. + * Creates a new pull request. Maintainer's permissions aware. * - * @param id - * the id - * @return the release + * @param title + * Required. The title of the pull request. + * @param head + * Required. The name of the branch where your changes are implemented. For cross-repository pull + * requests in the same network, namespace head with a user like this: username:branch. + * @param base + * Required. The name of the branch you want your changes pulled into. This should be an existing branch + * on the current repository. + * @param body + * The contents of the pull request. This is the markdown description of a pull request. + * @param maintainerCanModify + * Indicates whether maintainers can modify the pull request. + * @return the gh pull request * @throws IOException * the io exception */ - public GHRelease getRelease(long id) throws IOException { - try { - return root().createRequest() - .withUrlPath(getApiTailUrl("releases/" + id)) - .fetch(GHRelease.class) - .wrap(this); - } catch (FileNotFoundException e) { - return null; // no release for this id - } + public GHPullRequest createPullRequest(String title, + String head, + String base, + String body, + boolean maintainerCanModify) throws IOException { + return createPullRequest(title, head, base, body, maintainerCanModify, false); } /** - * Gets release by tag name. + * Creates a new pull request. Maintainer's permissions and draft aware. * - * @param tag - * the tag - * @return the release by tag name + * @param title + * Required. The title of the pull request. + * @param head + * Required. The name of the branch where your changes are implemented. For cross-repository pull + * requests in the same network, namespace head with a user like this: username:branch. + * @param base + * Required. The name of the branch you want your changes pulled into. This should be an existing branch + * on the current repository. + * @param body + * The contents of the pull request. This is the markdown description of a pull request. + * @param maintainerCanModify + * Indicates whether maintainers can modify the pull request. + * @param draft + * Indicates whether to create a draft pull request or not. + * @return the gh pull request * @throws IOException * the io exception */ - public GHRelease getReleaseByTagName(String tag) throws IOException { - try { - return root().createRequest() - .withUrlPath(getApiTailUrl("releases/tags/" + tag)) - .fetch(GHRelease.class) - .wrap(this); - } catch (FileNotFoundException e) { - return null; // no release for this tag - } + public GHPullRequest createPullRequest(String title, + String head, + String base, + String body, + boolean maintainerCanModify, + boolean draft) throws IOException { + return root().createRequest() + .method("POST") + .with("title", title) + .with("head", head) + .with("base", base) + .with("body", body) + .with("maintainer_can_modify", maintainerCanModify) + .with("draft", draft) + .withUrlPath(getApiTailUrl("pulls")) + .fetch(GHPullRequest.class) + .wrapUp(this); } /** - * Gets size. + * Retrieves the currently configured hooks. * - * @return the size + * @return the hooks + * @throws IOException + * the io exception */ - public int getSize() { - return size; + public List getHooks() throws IOException { + return GHHooks.repoContext(this, owner).getHooks(); } /** - * Forked repositories have a 'source' attribute that specifies the ultimate source of the forking chain. + * Gets hook. * - * @return {@link GHRepository} that points to the root repository where this repository is forked (indirectly or - * directly) from. Otherwise null. + * @param id + * the id + * @return the hook * @throws IOException * the io exception - * @see #getParent() #getParent() */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getSource() throws IOException { - if (fork && source == null) { - populate(); - } - if (source == null) { - return null; - } - - return source; + public GHHook getHook(int id) throws IOException { + return GHHooks.repoContext(this, owner).getHook(id); } /** - * Gets the SSH URL to access this repository, such as git@github.com:rails/rails.git + * Deletes hook. * - * @return the ssh url + * @param id + * the id + * @throws IOException + * the io exception */ - public String getSshUrl() { - return sshUrl; + public void deleteHook(int id) throws IOException { + GHHooks.repoContext(this, owner).deleteHook(id); } /** - * Gets stargazers count. + * Sets {@link #getCompare(String, String)} to return a {@link GHCompare} that uses a paginated commit list instead + * of limiting to 250 results. * - * @return the stargazers count + * By default, {@link GHCompare} returns all commits in the comparison as part of the request, limited to 250 + * results. More recently GitHub added the ability to return the commits as a paginated query allowing for more than + * 250 results. + * + * @param value + * true if you want commits returned in paginated form. */ - public int getStargazersCount() { - return stargazersCount; + public void setCompareUsePaginatedCommits(boolean value) { + compareUsePaginatedCommits = value; } /** - * Returns the statistics for this repository. + * Gets a comparison between 2 points in the repository. This would be similar to calling + * git log id1...id2 against a local repository. * - * @return the statistics + * @param id1 + * an identifier for the first point to compare from, this can be a sha1 ID (for a commit, tag etc) or a + * direct tag name + * @param id2 + * an identifier for the second point to compare to. Can be the same as the first point. + * @return the comparison output + * @throws IOException + * on failure communicating with GitHub */ - public GHRepositoryStatistics getStatistics() { - // TODO: Use static object and introduce refresh() method, - // instead of returning new object each time. - return new GHRepositoryStatistics(this); + public GHCompare getCompare(String id1, String id2) throws IOException { + final Requester requester = root().createRequest() + .withUrlPath(getApiTailUrl(String.format("compare/%s...%s", id1, id2))); + + if (compareUsePaginatedCommits) { + requester.with("per_page", 1).with("page", 1); + } + requester.injectMappingValue("GHCompare_usePaginatedCommits", compareUsePaginatedCommits); + GHCompare compare = requester.fetch(GHCompare.class); + return compare.lateBind(this); } /** - * Gets subscribers count. + * Gets compare. * - * @return the subscribers count + * @param id1 + * the id 1 + * @param id2 + * the id 2 + * @return the compare + * @throws IOException + * the io exception */ - public int getSubscribersCount() { - return subscribersCount; + public GHCompare getCompare(GHCommit id1, GHCommit id2) throws IOException { + return getCompare(id1.getSHA1(), id2.getSHA1()); } /** - * Returns the current subscription. + * Gets compare. * - * @return null if no subscription exists. + * @param id1 + * the id 1 + * @param id2 + * the id 2 + * @return the compare * @throws IOException * the io exception */ - public GHSubscription getSubscription() throws IOException { - try { - return root().createRequest() - .withUrlPath(getApiTailUrl("subscription")) - .fetch(GHSubscription.class) - .wrapUp(this); - } catch (FileNotFoundException e) { - return null; + public GHCompare getCompare(GHBranch id1, GHBranch id2) throws IOException { + + GHRepository owner1 = id1.getOwner(); + GHRepository owner2 = id2.getOwner(); + + // If the owner of the branches is different, we have a cross-fork compare. + if (owner1 != null && owner2 != null) { + String ownerName1 = owner1.getOwnerName(); + String ownerName2 = owner2.getOwnerName(); + if (!StringUtils.equals(ownerName1, ownerName2)) { + String qualifiedName1 = String.format("%s:%s", ownerName1, id1.getName()); + String qualifiedName2 = String.format("%s:%s", ownerName2, id2.getName()); + return getCompare(qualifiedName1, qualifiedName2); + } } + + return getCompare(id1.getName(), id2.getName()); } /** - * Gets the Subversion URL to access this repository: https://github.com/rails/rails + * Retrieves all refs for the github repository. * - * @return the svn url + * @return an array of GHRef elements corresponding with the refs in the remote repository. + * @throws IOException + * on failure communicating with GitHub */ - public String getSvnUrl() { - return svnUrl; + public GHRef[] getRefs() throws IOException { + return listRefs().toArray(); } /** - * Returns the annotated tag object. Only valid if the {@link GHRef#getObject()} has a - * {@link GHRef.GHObject#getType()} of {@code tag}. + * Retrieves all refs for the github repository. * - * @param sha - * the sha of the tag object - * @return the annotated tag object + * @return paged iterable of all refs * @throws IOException - * the io exception + * on failure communicating with GitHub, potentially due to an invalid ref type being requested */ - public GHTagObject getTagObject(String sha) throws IOException { - return root().createRequest().withUrlPath(getApiTailUrl("git/tags/" + sha)).fetch(GHTagObject.class).wrap(this); + public PagedIterable listRefs() throws IOException { + return listRefs(""); } /** - * If this repository belongs to an organization, return a set of teams. + * Retrieves all refs of the given type for the current GitHub repository. * - * @return the teams + * @param refType + * the type of reg to search for e.g. tags or commits + * @return an array of all refs matching the request type * @throws IOException - * the io exception + * on failure communicating with GitHub, potentially due to an invalid ref type being requested */ - public Set getTeams() throws IOException { - GHOrganization org = root().getOrganization(getOwnerName()); - return root().createRequest() - .withUrlPath(getApiTailUrl("teams")) - .toIterable(GHTeam[].class, item -> item.wrapUp(org)) - .toSet(); + public GHRef[] getRefs(String refType) throws IOException { + return listRefs(refType).toArray(); } /** - * Get Repository template was the repository created from. + * Retrieves all refs of the given type for the current GitHub repository. * - * @return the repository template + * @param refType + * the type of reg to search for e.g. tags or commits + * @return paged iterable of all refs of the specified type + * @throws IOException + * on failure communicating with GitHub, potentially due to an invalid ref type being requested */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHRepository getTemplateRepository() { - return templateRepository; + public PagedIterable listRefs(String refType) throws IOException { + return GHRef.readMatching(this, refType); } /** - * Get the top 10 popular contents over the last 14 days as described on - * https://docs.github.com/en/rest/metrics/traffic?apiVersion=2022-11-28#get-top-referral-paths + * Retrieve a ref of the given type for the current GitHub repository. * - * @return list of top referral paths + * @param refName + * eg: heads/branch + * @return refs matching the request type * @throws IOException - * the io exception + * on failure communicating with GitHub, potentially due to an invalid ref type being requested */ - public List getTopReferralPaths() throws IOException { - return Arrays.asList(root().createRequest() - .method("GET") - .withUrlPath(getApiTailUrl("/traffic/popular/paths")) - .fetch(GHRepositoryTrafficTopReferralPath[].class)); + public GHRef getRef(String refName) throws IOException { + return GHRef.read(this, refName); } /** - * Get the top 10 referrers over the last 14 days as described on - * https://docs.github.com/en/rest/metrics/traffic?apiVersion=2022-11-28#get-top-referral-sources + * Returns the annotated tag object. Only valid if the {@link GHRef#getObject()} has a + * {@link GHRef.GHObject#getType()} of {@code tag}. * - * @return list of top referrers + * @param sha + * the sha of the tag object + * @return the annotated tag object * @throws IOException * the io exception */ - public List getTopReferralSources() throws IOException { - return Arrays.asList(root().createRequest() - .method("GET") - .withUrlPath(getApiTailUrl("/traffic/popular/referrers")) - .fetch(GHRepositoryTrafficTopReferralSources[].class)); + public GHTagObject getTagObject(String sha) throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("git/tags/" + sha)).fetch(GHTagObject.class).wrap(this); } /** @@ -2157,6 +1855,15 @@ public GHTree getTree(String sha) throws IOException { return root().createRequest().withUrlPath(url).fetch(GHTree.class).wrap(this); } + /** + * Create tree gh tree builder. + * + * @return the gh tree builder + */ + public GHTreeBuilder createTree() { + return new GHTreeBuilder(this); + } + /** * Retrieves the tree for the current GitHub repository, recursively as described in here: * https://developer.github.com/v3/git/trees/#get-a-tree-recursively @@ -2175,659 +1882,927 @@ public GHTree getTreeRecursive(String sha, int recursive) throws IOException { } /** - * Gets a repository variable. + * Obtains the metadata & the content of a blob. * - * @param name - * the variable name (e.g. test-variable) - * @return the variable + *

+ * This method retrieves the whole content in memory, so beware when you are dealing with large BLOB. + * + * @param blobSha + * the blob sha + * @return the blob * @throws IOException * the io exception + * @see Get a blob + * @see #readBlob(String) #readBlob(String) */ - public GHRepositoryVariable getVariable(String name) throws IOException { - return GHRepositoryVariable.read(this, name); + public GHBlob getBlob(String blobSha) throws IOException { + String target = getApiTailUrl("git/blobs/" + blobSha); + return root().createRequest().withUrlPath(target).fetch(GHBlob.class); } /** - * https://developer.github.com/v3/repos/traffic/#views + * Create blob gh blob builder. * - * @return the view traffic + * @return the gh blob builder + */ + public GHBlobBuilder createBlob() { + return new GHBlobBuilder(this); + } + + /** + * Reads the content of a blob as a stream for better efficiency. + * + * @param blobSha + * the blob sha + * @return the input stream * @throws IOException * the io exception + * @see Get a blob + * @see #getBlob(String) #getBlob(String) */ - public GHRepositoryViewTraffic getViewTraffic() throws IOException { - return root().createRequest().withUrlPath(getApiTailUrl("/traffic/views")).fetch(GHRepositoryViewTraffic.class); + public InputStream readBlob(String blobSha) throws IOException { + String target = getApiTailUrl("git/blobs/" + blobSha); + + // https://developer.github.com/v3/media/ describes this media type + return root().createRequest() + .withHeader("Accept", "application/vnd.github.raw") + .withUrlPath(target) + .fetchStream(Requester::copyInputStream); + } + + /** + * Gets a commit object in this repository. + * + * @param sha1 + * the sha 1 + * @return the commit + * @throws IOException + * the io exception + */ + public GHCommit getCommit(String sha1) throws IOException { + GHCommit c = commits.get(sha1); + if (c == null) { + c = root().createRequest() + .withUrlPath(String.format("/repos/%s/%s/commits/%s", getOwnerName(), name, sha1)) + .fetch(GHCommit.class) + .wrapUp(this); + commits.put(sha1, c); + } + return c; + } + + /** + * Create commit gh commit builder. + * + * @return the gh commit builder + */ + public GHCommitBuilder createCommit() { + return new GHCommitBuilder(this); + } + + /** + * Lists all the commits. + * + * @return the paged iterable + */ + public PagedIterable listCommits() { + return root().createRequest() + .withUrlPath(String.format("/repos/%s/%s/commits", getOwnerName(), name)) + .toIterable(GHCommit[].class, item -> item.wrapUp(this)); + } + + /** + * Search commits by specifying filters through a builder pattern. + * + * @return the gh commit query builder + */ + public GHCommitQueryBuilder queryCommits() { + return new GHCommitQueryBuilder(this); } /** - * Gets the visibility of the repository. + * Lists up all the commit comments in this repository. * - * @return the visibility + * @return the paged iterable */ - public Visibility getVisibility() { - if (visibility == null) { - try { - populate(); - } catch (final IOException e) { - // Convert this to a runtime exception to avoid messy method signature - throw new GHException("Could not populate the visibility of the repository", e); - } - } - return Visibility.from(visibility); + public PagedIterable listCommitComments() { + return root().createRequest() + .withUrlPath(String.format("/repos/%s/%s/comments", getOwnerName(), name)) + .toIterable(GHCommitComment[].class, item -> item.wrap(this)); } /** - * Gets the count of watchers. + * Lists all comments on a specific commit. * - * @return the watchers + * @param commitSha + * the hash of the commit + * + * @return the paged iterable */ - public int getWatchersCount() { - return watchersCount; + public PagedIterable listCommitComments(String commitSha) { + return root().createRequest() + .withUrlPath(String.format("/repos/%s/%s/commits/%s/comments", getOwnerName(), name, commitSha)) + .toIterable(GHCommitComment[].class, item -> item.wrap(this)); } /** - * Gets a workflow by name of the file. + * Gets the basic license details for the repository. * - * @param nameOrId - * either the name of the file (e.g. my-workflow.yml) or the id as a string - * @return the workflow run + * @return null if there's no license. * @throws IOException - * the io exception + * as usual but also if you don't use the preview connector */ - public GHWorkflow getWorkflow(String nameOrId) throws IOException { - return root().createRequest() - .withUrlPath(getApiTailUrl("actions/workflows"), nameOrId) - .fetch(GHWorkflow.class) - .wrapUp(this); + public GHLicense getLicense() throws IOException { + GHContentWithLicense lic = getLicenseContent_(); + return lic != null ? lic.license : null; } /** - * Gets a workflow by id. + * Retrieves the contents of the repository's license file - makes an additional API call. * - * @param id - * the id of the workflow run - * @return the workflow run + * @return details regarding the license contents, or null if there's no license. * @throws IOException - * the io exception + * as usual but also if you don't use the preview connector */ - public GHWorkflow getWorkflow(long id) throws IOException { - return getWorkflow(String.valueOf(id)); + public GHContent getLicenseContent() throws IOException { + return getLicenseContent_(); + } + + private GHContentWithLicense getLicenseContent_() throws IOException { + try { + return root().createRequest() + .withUrlPath(getApiTailUrl("license")) + .fetch(GHContentWithLicense.class) + .wrap(this); + } catch (FileNotFoundException e) { + return null; + } } /** - * Gets a job from a workflow run by id. + * /** Lists all the commit statuses attached to the given commit, newer ones first. * - * @param id - * the id of the job - * @return the job + * @param sha1 + * the sha 1 + * @return the paged iterable * @throws IOException * the io exception */ - public GHWorkflowJob getWorkflowJob(long id) throws IOException { + public PagedIterable listCommitStatuses(final String sha1) throws IOException { return root().createRequest() - .withUrlPath(getApiTailUrl("/actions/jobs"), String.valueOf(id)) - .fetch(GHWorkflowJob.class) - .wrapUp(this); + .withUrlPath(String.format("/repos/%s/%s/statuses/%s", getOwnerName(), name, sha1)) + .toIterable(GHCommitStatus[].class, null); } /** - * Gets a workflow run. + * Gets the last status of this commit, which is what gets shown in the UI. * - * @param id - * the id of the workflow run - * @return the workflow run + * @param sha1 + * the sha 1 + * @return the last commit status * @throws IOException * the io exception */ - public GHWorkflowRun getWorkflowRun(long id) throws IOException { - return root().createRequest() - .withUrlPath(getApiTailUrl("actions/runs"), String.valueOf(id)) - .fetch(GHWorkflowRun.class) - .wrapUp(this); + public GHCommitStatus getLastCommitStatus(String sha1) throws IOException { + List v = listCommitStatuses(sha1).toList(); + return v.isEmpty() ? null : v.get(0); } /** - * Has admin access boolean. + * Gets check runs for given ref. * - * @return the boolean + * @param ref + * ref + * @return check runs for given ref + * @throws IOException + * the io exception + * @see List check runs + * for a specific ref */ - public boolean hasAdminAccess() { - return permissions != null && permissions.admin; + public PagedIterable getCheckRuns(String ref) throws IOException { + GitHubRequest request = root().createRequest() + .withUrlPath(String.format("/repos/%s/%s/commits/%s/check-runs", getOwnerName(), name, ref)) + .build(); + return new GHCheckRunsIterable(this, request); } /** - * Checks if the given user is an assignee for this repository. + * Gets check runs for given ref which validate provided parameters * - * @param u - * the u - * @return the boolean + * @param ref + * the Git reference + * @param params + * a map of parameters to filter check runs + * @return check runs for the given ref * @throws IOException * the io exception + * @see List check runs + * for a specific ref */ - public boolean hasAssignee(GHUser u) throws IOException { - return root().createRequest().withUrlPath(getApiTailUrl("assignees/" + u.getLogin())).fetchHttpStatusCode() - / 100 == 2; + public PagedIterable getCheckRuns(String ref, Map params) throws IOException { + GitHubRequest request = root().createRequest() + .withUrlPath(String.format("/repos/%s/%s/commits/%s/check-runs", getOwnerName(), name, ref)) + .with(params) + .build(); + return new GHCheckRunsIterable(this, request); } /** - * Has downloads boolean. + * Creates a commit status. * - * @return the boolean + * @param sha1 + * the sha 1 + * @param state + * the state + * @param targetUrl + * Optional parameter that points to the URL that has more details. + * @param description + * Optional short description. + * @param context + * Optional commit status context. + * @return the gh commit status + * @throws IOException + * the io exception */ - public boolean hasDownloads() { - return hasDownloads; + public GHCommitStatus createCommitStatus(String sha1, + GHCommitState state, + String targetUrl, + String description, + String context) throws IOException { + return root().createRequest() + .method("POST") + .with("state", state) + .with("target_url", targetUrl) + .with("description", description) + .with("context", context) + .withUrlPath(String.format("/repos/%s/%s/statuses/%s", getOwnerName(), this.name, sha1)) + .fetch(GHCommitStatus.class); } /** - * Has issues boolean. + * Create commit status gh commit status. * - * @return the boolean + * @param sha1 + * the sha 1 + * @param state + * the state + * @param targetUrl + * the target url + * @param description + * the description + * @return the gh commit status + * @throws IOException + * the io exception + * @see #createCommitStatus(String, GHCommitState, String, String, String) #createCommitStatus(String, + * GHCommitState,String,String,String) */ - public boolean hasIssues() { - return hasIssues; + public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, String targetUrl, String description) + throws IOException { + return createCommitStatus(sha1, state, targetUrl, description, null); } /** - * Has pages boolean. + * Creates a check run for a commit. * - * @return the boolean + * @param name + * an identifier for the run + * @param headSHA + * the commit hash + * @return a builder which you should customize, then call {@link GHCheckRunBuilder#create} */ - public boolean hasPages() { - return hasPages; + public @NonNull GHCheckRunBuilder createCheckRun(@NonNull String name, @NonNull String headSHA) { + return new GHCheckRunBuilder(this, name, headSHA); } /** - * Check if a user has at least the given permission in this repository. + * Updates an existing check run. * - * @param user - * the user - * @param permission - * the permission to check - * @return true if the user has at least this permission level - * @throws IOException - * the io exception + * @param checkId + * the existing checkId + * @return a builder which you should customize, then call {@link GHCheckRunBuilder#create} */ - public boolean hasPermission(GHUser user, GHPermissionType permission) throws IOException { - return hasPermission(user.getLogin(), permission); + public @NonNull GHCheckRunBuilder updateCheckRun(long checkId) { + return new GHCheckRunBuilder(this, checkId); } /** - * Check if a user has at least the given permission in this repository. + * Lists repository events. * - * @param user - * a {@link GHUser#getLogin} - * @param permission - * the permission to check - * @return true if the user has at least this permission level + * @return the paged iterable * @throws IOException * the io exception */ - public boolean hasPermission(String user, GHPermissionType permission) throws IOException { - return getPermission(user).implies(permission); - } - - /** - * Has projects boolean. - * - * @return the boolean - */ - public boolean hasProjects() { - return hasProjects; + public PagedIterable listEvents() throws IOException { + return root().createRequest() + .withUrlPath(String.format("/repos/%s/%s/events", getOwnerName(), name)) + .toIterable(GHEventInfo[].class, null); } /** - * Has pull access boolean. + * Lists labels in this repository. + *

+ * https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository * - * @return the boolean + * @return the paged iterable + * @throws IOException + * the io exception */ - public boolean hasPullAccess() { - return permissions != null && permissions.pull; + public PagedIterable listLabels() throws IOException { + return GHLabel.readAll(this); } /** - * Has push access boolean. + * Gets label. * - * @return the boolean + * @param name + * the name + * @return the label + * @throws IOException + * the io exception */ - public boolean hasPushAccess() { - return permissions != null && permissions.push; + public GHLabel getLabel(String name) throws IOException { + return GHLabel.read(this, name); } /** - * Has wiki boolean. + * Create label gh label. * - * @return the boolean + * @param name + * the name + * @param color + * the color + * @return the gh label + * @throws IOException + * the io exception */ - public boolean hasWiki() { - return hasWiki; + public GHLabel createLabel(String name, String color) throws IOException { + return GHLabel.create(this).name(name).color(color).description("").done(); } /** - * Hash code. + * Description is still in preview. * - * @return the int + * @param name + * the name + * @param color + * the color + * @param description + * the description + * @return gh label + * @throws IOException + * the io exception */ - @Override - public int hashCode() { - return ("Repository:" + getOwnerName() + ":" + name).hashCode(); + public GHLabel createLabel(String name, String color, String description) throws IOException { + return GHLabel.create(this).name(name).color(color).description(description).done(); } /** - * Is allow private forks + * Lists all the invitations. * - * @return the boolean + * @return the paged iterable */ - public boolean isAllowForking() { - return allowForking; + public PagedIterable listInvitations() { + return root().createRequest() + .withUrlPath(String.format("/repos/%s/%s/invitations", getOwnerName(), name)) + .toIterable(GHInvitation[].class, null); } /** - * Is allow merge commit boolean. + * Lists all the subscribers (aka watchers.) + *

+ * https://developer.github.com/v3/activity/watching/ * - * @return the boolean + * @return the paged iterable */ - public boolean isAllowMergeCommit() { - return allowMergeCommit; + public PagedIterable listSubscribers() { + return listUsers("subscribers"); } /** - * Is allow rebase merge boolean. + * Lists all the users who have starred this repo based on new version of the API, having extended information like + * the time when the repository was starred. * - * @return the boolean + * @return the paged iterable + * @deprecated Use {@link #listStargazers()} */ - public boolean isAllowRebaseMerge() { - return allowRebaseMerge; + @Deprecated + public PagedIterable listStargazers2() { + return listStargazers(); } /** - * Is allow squash merge boolean. + * Lists all the users who have starred this repo based on new version of the API, having extended information like + * the time when the repository was starred. * - * @return the boolean + * @return the paged iterable */ - public boolean isAllowSquashMerge() { - return allowSquashMerge; + public PagedIterable listStargazers() { + return root().createRequest() + .withAccept("application/vnd.github.star+json") + .withUrlPath(getApiTailUrl("stargazers")) + .toIterable(GHStargazer[].class, item -> item.wrapUp(this)); + } + + private PagedIterable listUsers(final String suffix) { + return listUsers(root().createRequest(), suffix); + } + + private PagedIterable listUsers(Requester requester, final String suffix) { + return requester.withUrlPath(getApiTailUrl(suffix)).toIterable(GHUser[].class, null); } /** - * Is archived boolean. + * See https://api.github.com/hooks for possible names and their configuration scheme. TODO: produce type-safe + * binding * - * @return the boolean + * @param name + * Type of the hook to be created. See https://api.github.com/hooks for possible names. + * @param config + * The configuration hash. + * @param events + * Can be null. Types of events to hook into. + * @param active + * the active + * @return the gh hook + * @throws IOException + * the io exception */ - public boolean isArchived() { - return archived; + public GHHook createHook(String name, Map config, Collection events, boolean active) + throws IOException { + return GHHooks.repoContext(this, owner).createHook(name, config, events, active); } /** - * Checks if the given user is a collaborator for this repository. + * Create web hook gh hook. * - * @param user - * a {@link GHUser} - * @return true if the user is a collaborator for this repository + * @param url + * the url + * @param events + * the events + * @return the gh hook * @throws IOException * the io exception */ - public boolean isCollaborator(GHUser user) throws IOException { - return root().createRequest() - .withUrlPath(getApiTailUrl("collaborators/" + user.getLogin())) - .fetchHttpStatusCode() == 204; + public GHHook createWebHook(URL url, Collection events) throws IOException { + return createHook("web", Collections.singletonMap("url", url.toExternalForm()), events, true); } /** - * Automatically deleting head branches when pull requests are merged. + * Create web hook gh hook. * - * @return the boolean + * @param url + * the url + * @return the gh hook + * @throws IOException + * the io exception */ - public boolean isDeleteBranchOnMerge() { - return deleteBranchOnMerge; + public GHHook createWebHook(URL url) throws IOException { + return createWebHook(url, null); } /** - * Is disabled boolean. + * Gets branches by {@linkplain GHBranch#getName() their names}. * - * @return the boolean + * @return the branches + * @throws IOException + * the io exception */ - public boolean isDisabled() { - return disabled; + public Map getBranches() throws IOException { + Map r = new TreeMap(); + for (GHBranch p : root().createRequest() + .withUrlPath(getApiTailUrl("branches")) + .toIterable(GHBranch[].class, item -> item.wrap(this)) + .toArray()) { + r.put(p.getName(), p); + } + return r; } /** - * Is fork boolean. + * Gets branch. * - * @return the boolean + * @param name + * the name + * @return the branch + * @throws IOException + * the io exception */ - public boolean isFork() { - return fork; + public GHBranch getBranch(String name) throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("branches/" + name)).fetch(GHBranch.class).wrap(this); } /** - * Is private boolean. + * Lists up all the milestones in this repository. * - * @return the boolean + * @param state + * the state + * @return the paged iterable */ - public boolean isPrivate() { - return isPrivate; + public PagedIterable listMilestones(final GHIssueState state) { + return root().createRequest() + .with("state", state) + .withUrlPath(getApiTailUrl("milestones")) + .toIterable(GHMilestone[].class, item -> item.lateBind(this)); } /** - * Is template boolean. + * Gets milestone. * - * @return the boolean + * @param number + * the number + * @return the milestone + * @throws IOException + * the io exception */ - public boolean isTemplate() { - if (isTemplate == null) { - try { - populate(); - } catch (IOException e) { - // Convert this to a runtime exception to avoid messy method signature - throw new GHException("Could not populate the template setting of the repository", e); - } - // if this somehow is not populated, set it to false; - isTemplate = Boolean.TRUE.equals(isTemplate); + public GHMilestone getMilestone(int number) throws IOException { + GHMilestone m = milestones.get(number); + if (m == null) { + m = root().createRequest().withUrlPath(getApiTailUrl("milestones/" + number)).fetch(GHMilestone.class); + m.owner = this; + milestones.put(m.getNumber(), m); } - return isTemplate; + return m; } /** - * Check, if vulnerability alerts are enabled for this repository - * (https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#check-if-vulnerability-alerts-are-enabled-for-a-repository). + * Gets file content. * - * @return true, if vulnerability alerts are enabled + * @param path + * the path + * @return the file content * @throws IOException * the io exception */ - public boolean isVulnerabilityAlertsEnabled() throws IOException { - return root().createRequest() - .method("GET") - .withUrlPath(getApiTailUrl("/vulnerability-alerts")) - .fetchHttpStatusCode() == 204; + public GHContent getFileContent(String path) throws IOException { + return getFileContent(path, null); } /** - * Lists all the artifacts of this repository. + * Gets file content. * - * @return the paged iterable + * @param path + * the path + * @param ref + * the ref + * @return the file content + * @throws IOException + * the io exception */ - public PagedIterable listArtifacts() { - return new GHArtifactsIterable(this, root().createRequest().withUrlPath(getApiTailUrl("actions/artifacts"))); + public GHContent getFileContent(String path, String ref) throws IOException { + Requester requester = root().createRequest(); + String target = getApiTailUrl("contents/" + path); + + return requester.with("ref", ref).withUrlPath(target).fetch(GHContent.class).wrap(this); } /** - * Lists all - * the - * available assignees to which issues may be assigned. + * Gets directory content. * - * @return the paged iterable + * @param path + * the path + * @return the directory content + * @throws IOException + * the io exception */ - public PagedIterable listAssignees() { - return listUsers("assignees"); + public List getDirectoryContent(String path) throws IOException { + return getDirectoryContent(path, null); } /** - * List all autolinks of a repo (admin only). - * (https://docs.github.com/en/rest/repos/autolinks?apiVersion=2022-11-28#get-all-autolinks-of-a-repository) + * Gets directory content. * - * @return all autolinks in the repo + * @param path + * the path + * @param ref + * the ref + * @return the directory content + * @throws IOException + * the io exception */ - public PagedIterable listAutolinks() { - return root().createRequest() - .withHeader("Accept", "application/vnd.github+json") - .withUrlPath(String.format("/repos/%s/%s/autolinks", getOwnerName(), getName())) - .toIterable(GHAutolink[].class, item -> item.lateBind(this)); + public List getDirectoryContent(String path, String ref) throws IOException { + Requester requester = root().createRequest(); + while (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } + String target = getApiTailUrl("contents/" + path); + + return requester.with("ref", ref) + .withUrlPath(target) + .toIterable(GHContent[].class, item -> item.wrap(this)) + .toList(); } /** - * List errors in the {@code CODEOWNERS} file. Note that GitHub skips lines with incorrect syntax; these are - * reported in the web interface, but not in the API call which this library uses. + * https://developer.github.com/v3/repos/contents/#get-the-readme * - * @return the list of errors + * @return the readme * @throws IOException * the io exception */ - public List listCodeownersErrors() throws IOException { - return root().createRequest() - .withUrlPath(getApiTailUrl("codeowners/errors")) - .fetch(GHCodeownersErrors.class).errors; + public GHContent getReadme() throws IOException { + Requester requester = root().createRequest(); + return requester.withUrlPath(getApiTailUrl("readme")).fetch(GHContent.class).wrap(this); } /** - * Lists up the collaborators on this repository. + * Create a repository variable. * - * @return Users paged iterable + * @param name + * the variable name (e.g. test-variable) + * @param value + * the value + * @throws IOException + * the io exception */ - public PagedIterable listCollaborators() { - return listUsers("collaborators"); + public void createVariable(String name, String value) throws IOException { + GHRepositoryVariable.create(this).name(name).value(value).done(); } /** - * Lists up the collaborators on this repository. + * Gets a repository variable. * - * @param affiliation - * Filter users by affiliation - * @return Users paged iterable + * @param name + * the variable name (e.g. test-variable) + * @return the variable + * @throws IOException + * the io exception */ - public PagedIterable listCollaborators(CollaboratorAffiliation affiliation) { - return listUsers(root().createRequest().with("affiliation", affiliation), "collaborators"); + public GHRepositoryVariable getVariable(String name) throws IOException { + return GHRepositoryVariable.read(this, name); } /** - * Lists up all the commit comments in this repository. + * Creates a new content, or update an existing content. * - * @return the paged iterable + * @return the gh content builder */ - public PagedIterable listCommitComments() { - return root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/comments", getOwnerName(), name)) - .toIterable(GHCommitComment[].class, item -> item.wrap(this)); + public GHContentBuilder createContent() { + return new GHContentBuilder(this); } /** - * Lists all comments on a specific commit. - * - * @param commitSha - * the hash of the commit + * Create milestone gh milestone. * - * @return the paged iterable + * @param title + * the title + * @param description + * the description + * @return the gh milestone + * @throws IOException + * the io exception */ - public PagedIterable listCommitComments(String commitSha) { + public GHMilestone createMilestone(String title, String description) throws IOException { return root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/commits/%s/comments", getOwnerName(), name, commitSha)) - .toIterable(GHCommitComment[].class, item -> item.wrap(this)); + .method("POST") + .with("title", title) + .with("description", description) + .withUrlPath(getApiTailUrl("milestones")) + .fetch(GHMilestone.class) + .lateBind(this); } /** - * /** Lists all the commit statuses attached to the given commit, newer ones first. + * Add deploy key gh deploy key. * - * @param sha1 - * the sha 1 - * @return the paged iterable + * @param title + * the title + * @param key + * the key + * @return the gh deploy key + * @throws IOException + * the io exception */ - public PagedIterable listCommitStatuses(final String sha1) { - return root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/statuses/%s", getOwnerName(), name, sha1)) - .toIterable(GHCommitStatus[].class, null); + public GHDeployKey addDeployKey(String title, String key) throws IOException { + return addDeployKey(title, key, false); } /** - * Lists all the commits. + * Add deploy key gh deploy key. * - * @return the paged iterable + * @param title + * the title + * @param key + * the key + * @param readOnly + * read-only ability of the key + * @return the gh deploy key + * @throws IOException + * the io exception */ - public PagedIterable listCommits() { + public GHDeployKey addDeployKey(String title, String key, boolean readOnly) throws IOException { return root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/commits", getOwnerName(), name)) - .toIterable(GHCommit[].class, item -> item.wrapUp(this)); - } - - /** - * List contributors paged iterable. - * - * @return the paged iterable - */ - public PagedIterable listContributors() { - return listContributors(null); + .method("POST") + .with("title", title) + .with("key", key) + .with("read_only", readOnly) + .withUrlPath(getApiTailUrl("keys")) + .fetch(GHDeployKey.class) + .lateBind(this); } /** - * List contributors paged iterable. + * Gets deploy keys. * - * @param includeAnonymous - * whether to include anonymous contributors - * @return the paged iterable - * @see - * GitHub API - List Repository Contributors + * @return the deploy keys + * @throws IOException + * the io exception */ - public PagedIterable listContributors(Boolean includeAnonymous) { + public List getDeployKeys() throws IOException { return root().createRequest() - .withUrlPath(getApiTailUrl("contributors")) - .with("anon", includeAnonymous) - .toIterable(Contributor[].class, null); + .withUrlPath(getApiTailUrl("keys")) + .toIterable(GHDeployKey[].class, item -> item.lateBind(this)) + .toList(); } /** - * List deployments paged iterable. + * Forked repositories have a 'source' attribute that specifies the ultimate source of the forking chain. * - * @param sha - * the sha - * @param ref - * the ref - * @param task - * the task - * @param environment - * the environment - * @return the paged iterable + * @return {@link GHRepository} that points to the root repository where this repository is forked (indirectly or + * directly) from. Otherwise null. + * @throws IOException + * the io exception + * @see #getParent() #getParent() */ - public PagedIterable listDeployments(String sha, String ref, String task, String environment) { - return root().createRequest() - .with("sha", sha) - .with("ref", ref) - .with("task", task) - .with("environment", environment) - .withUrlPath(getApiTailUrl("deployments")) - .toIterable(GHDeployment[].class, item -> item.wrap(this)); - } + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getSource() throws IOException { + if (fork && source == null) { + populate(); + } + if (source == null) { + return null; + } - /** - * Lists repository events. - * - * @return the paged iterable - */ - public PagedIterable listEvents() { - return root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/events", getOwnerName(), name)) - .toIterable(GHEventInfo[].class, null); + return source; } /** - * Lists all the direct forks of this repository, sorted by github api default, currently {@link ForkSort#NEWEST - * ForkSort.NEWEST}*. + * Forked repositories have a 'parent' attribute that specifies the repository this repository is directly forked + * from. If we keep traversing {@link #getParent()} until it returns null, that is {@link #getSource()}. * - * @return the paged iterable + * @return {@link GHRepository} that points to the repository where this repository is forked directly from. + * Otherwise null. + * @throws IOException + * the io exception + * @see #getSource() #getSource() */ - public PagedIterable listForks() { - return listForks(null); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getParent() throws IOException { + if (fork && parent == null) { + populate(); + } + + if (parent == null) { + return null; + } + return parent; } /** - * Lists all the direct forks of this repository, sorted by the given sort order. + * Subscribes to this repository to get notifications. * - * @param sort - * the sort order. If null, defaults to github api default, currently {@link ForkSort#NEWEST - * ForkSort.NEWEST}. - * @return the paged iterable + * @param subscribed + * the subscribed + * @param ignored + * the ignored + * @return the gh subscription + * @throws IOException + * the io exception */ - public PagedIterable listForks(final ForkSort sort) { + public GHSubscription subscribe(boolean subscribed, boolean ignored) throws IOException { return root().createRequest() - .with("sort", sort) - .withUrlPath(getApiTailUrl("forks")) - .toIterable(GHRepository[].class, null); + .method("PUT") + .with("subscribed", subscribed) + .with("ignored", ignored) + .withUrlPath(getApiTailUrl("subscription")) + .fetch(GHSubscription.class) + .wrapUp(this); } /** - * Lists all the invitations. + * Returns the current subscription. * - * @return the paged iterable + * @return null if no subscription exists. + * @throws IOException + * the io exception */ - public PagedIterable listInvitations() { - return root().createRequest() - .withUrlPath(String.format("/repos/%s/%s/invitations", getOwnerName(), name)) - .toIterable(GHInvitation[].class, null); + public GHSubscription getSubscription() throws IOException { + try { + return root().createRequest() + .withUrlPath(getApiTailUrl("subscription")) + .fetch(GHSubscription.class) + .wrapUp(this); + } catch (FileNotFoundException e) { + return null; + } } - /** - * Get all issue events for this repository. See - * https://developer.github.com/v3/issues/events/#list-events-for-a-repository - * - * @return the paged iterable - */ - public PagedIterable listIssueEvents() { - return root().createRequest() - .withUrlPath(getApiTailUrl("issues/events")) - .toIterable(GHIssueEvent[].class, null); + // Only used within listCodeownersErrors(). + private static class GHCodeownersErrors { + public List errors; } /** - * Lists labels in this repository. - *

- * https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository + * List errors in the {@code CODEOWNERS} file. Note that GitHub skips lines with incorrect syntax; these are + * reported in the web interface, but not in the API call which this library uses. * - * @return the paged iterable + * @return the list of errors + * @throws IOException + * the io exception */ - public PagedIterable listLabels() { - return GHLabel.readAll(this); + public List listCodeownersErrors() throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("codeowners/errors")) + .fetch(GHCodeownersErrors.class).errors; } /** - * List languages for the specified repository. The value on the right of a language is the number of bytes of code - * written in that language. { "C": 78769, "Python": 7769 } + * List contributors paged iterable. * - * @return the map + * @return the paged iterable * @throws IOException * the io exception */ - public Map listLanguages() throws IOException { - HashMap result = new HashMap<>(); - root().createRequest().withUrlPath(getApiTailUrl("languages")).fetch(HashMap.class).forEach((key, value) -> { - Long addValue = -1L; - if (value instanceof Integer) { - addValue = Long.valueOf((Integer) value); - } - result.put(key.toString(), addValue); - }); - return result; + public PagedIterable listContributors() throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("contributors")).toIterable(Contributor[].class, null); } /** - * Lists up all the milestones in this repository. - * - * @param state - * the state - * @return the paged iterable + * The type Contributor. */ - public PagedIterable listMilestones(final GHIssueState state) { - return root().createRequest() - .with("state", state) - .withUrlPath(getApiTailUrl("milestones")) - .toIterable(GHMilestone[].class, item -> item.lateBind(this)); + public static class Contributor extends GHUser { + + /** + * Create default Contributor instance + */ + public Contributor() { + } + + private int contributions; + + /** + * Gets contributions. + * + * @return the contributions + */ + public int getContributions() { + return contributions; + } + + /** + * Hash code. + * + * @return the int + */ + @Override + public int hashCode() { + // We ignore contributions in the calculation + return super.hashCode(); + } + + /** + * Equals. + * + * @param obj + * the obj + * @return true, if successful + */ + @Override + public boolean equals(Object obj) { + // We ignore contributions in the calculation + return super.equals(obj); + } } /** - * List all the notifications in a repository for the current user. + * Returns the statistics for this repository. * - * @return the gh notification stream + * @return the statistics */ - public GHNotificationStream listNotifications() { - return new GHNotificationStream(root(), getApiTailUrl("/notifications")); + public GHRepositoryStatistics getStatistics() { + // TODO: Use static object and introduce refresh() method, + // instead of returning new object each time. + return new GHRepositoryStatistics(this); } /** - * Returns open projects for this repository. + * Create a project for this repository. * - * @return the paged iterable + * @param name + * the name + * @param body + * the body + * @return the gh project * @throws IOException * the io exception */ - public PagedIterable listProjects() throws IOException { - return listProjects(GHProject.ProjectStateFilter.OPEN); + public GHProject createProject(String name, String body) throws IOException { + return root().createRequest() + .method("POST") + .with("name", name) + .with("body", body) + .withUrlPath(getApiTailUrl("projects")) + .fetch(GHProject.class) + .lateBind(this); } /** @@ -2836,8 +2811,10 @@ public PagedIterable listProjects() throws IOException { * @param status * The status filter (all, open or closed). * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listProjects(final GHProject.ProjectStateFilter status) { + public PagedIterable listProjects(final GHProject.ProjectStateFilter status) throws IOException { return root().createRequest() .with("state", status) .withUrlPath(getApiTailUrl("projects")) @@ -2845,109 +2822,142 @@ public PagedIterable listProjects(final GHProject.ProjectStateFilter } /** - * Retrieves all refs for the github repository. + * Returns open projects for this repository. * - * @return paged iterable of all refs + * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listRefs() { - return listRefs(""); + public PagedIterable listProjects() throws IOException { + return listProjects(GHProject.ProjectStateFilter.OPEN); } /** - * Retrieves all refs of the given type for the current GitHub repository. + * Render a Markdown document. + *

+ * In {@linkplain MarkdownMode#GFM GFM mode}, issue numbers and user mentions are linked accordingly. * - * @param refType - * the type of reg to search for e.g. tags or commits - * @return paged iterable of all refs of the specified type + * @param text + * the text + * @param mode + * the mode + * @return the reader + * @throws IOException + * the io exception + * @see GitHub#renderMarkdown(String) GitHub#renderMarkdown(String) */ - public PagedIterable listRefs(String refType) { - return GHRef.readMatching(this, refType); + public Reader renderMarkdown(String text, MarkdownMode mode) throws IOException { + return new InputStreamReader( + root().createRequest() + .method("POST") + .with("text", text) + .with("mode", mode == null ? null : mode.toString()) + .with("context", getFullName()) + .withUrlPath("/markdown") + .fetchStream(Requester::copyInputStream), + "UTF-8"); } /** - * List releases paged iterable. + * List all the notifications in a repository for the current user. * - * @return the paged iterable + * @return the gh notification stream */ - public PagedIterable listReleases() { - return root().createRequest() - .withUrlPath(getApiTailUrl("releases")) - .toIterable(GHRelease[].class, item -> item.wrap(this)); + public GHNotificationStream listNotifications() { + return new GHNotificationStream(root(), getApiTailUrl("/notifications")); } /** - * Get all active rules that apply to the specified branch - * (https://docs.github.com/en/rest/repos/rules?apiVersion=2022-11-28#get-rules-for-a-branch). + * https://developer.github.com/v3/repos/traffic/#views * - * @param branch - * the branch - * @return the rules for branch + * @return the view traffic + * @throws IOException + * the io exception */ - public PagedIterable listRulesForBranch(String branch) { - return root().createRequest() - .method("GET") - .withUrlPath(getApiTailUrl("/rules/branches/" + branch)) - .toIterable(GHRepositoryRule[].class, null); + public GHRepositoryViewTraffic getViewTraffic() throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("/traffic/views")).fetch(GHRepositoryViewTraffic.class); } /** - * Lists all the users who have starred this repo based on new version of the API, having extended information like - * the time when the repository was starred. + * https://developer.github.com/v3/repos/traffic/#clones * - * @return the paged iterable + * @return the clone traffic + * @throws IOException + * the io exception */ - public PagedIterable listStargazers() { + public GHRepositoryCloneTraffic getCloneTraffic() throws IOException { return root().createRequest() - .withAccept("application/vnd.github.star+json") - .withUrlPath(getApiTailUrl("stargazers")) - .toIterable(GHStargazer[].class, item -> item.wrapUp(this)); + .withUrlPath(getApiTailUrl("/traffic/clones")) + .fetch(GHRepositoryCloneTraffic.class); } /** - * Lists all the users who have starred this repo based on new version of the API, having extended information like - * the time when the repository was starred. + * Hash code. * - * @return the paged iterable - * @deprecated Use {@link #listStargazers()} + * @return the int */ - @Deprecated - public PagedIterable listStargazers2() { - return listStargazers(); + @Override + public int hashCode() { + return ("Repository:" + getOwnerName() + ":" + name).hashCode(); } /** - * Lists all the subscribers (aka watchers.) - *

- * https://developer.github.com/v3/activity/watching/ + * Equals. * - * @return the paged iterable + * @param obj + * the obj + * @return true, if successful */ - public PagedIterable listSubscribers() { - return listUsers("subscribers"); + @Override + public boolean equals(Object obj) { + if (obj instanceof GHRepository) { + GHRepository that = (GHRepository) obj; + return this.getOwnerName().equals(that.getOwnerName()) && this.name.equals(that.name); + } + return false; } /** - * List tags paged iterable. + * Gets the api tail url. + * + * @param tail + * the tail + * @return the api tail url + */ + String getApiTailUrl(String tail) { + if (tail.length() > 0 && !tail.startsWith("/")) { + tail = '/' + tail; + } + return "/repos/" + full_name + tail; + } + + /** + * Get all issue events for this repository. See + * https://developer.github.com/v3/issues/events/#list-events-for-a-repository * * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listTags() { + public PagedIterable listIssueEvents() throws IOException { return root().createRequest() - .withUrlPath(getApiTailUrl("tags")) - .toIterable(GHTag[].class, item -> item.wrap(this)); + .withUrlPath(getApiTailUrl("issues/events")) + .toIterable(GHIssueEvent[].class, null); } /** - * Return the topics for this repository. See - * https://developer.github.com/v3/repos/#list-all-topics-for-a-repository + * Get a single issue event. See https://developer.github.com/v3/issues/events/#get-a-single-event * - * @return the list + * @param id + * the id + * @return the issue event * @throws IOException * the io exception */ - public List listTopics() throws IOException { - Topics topics = root().createRequest().withUrlPath(getApiTailUrl("topics")).fetch(Topics.class); - return topics.names; + public GHIssueEvent getIssueEvent(long id) throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("issues/events/" + id)).fetch(GHIssueEvent.class); } /** @@ -2960,30 +2970,32 @@ public PagedIterable listWorkflows() { } /** - * Search commits by specifying filters through a builder pattern. - * - * @return the gh commit query builder - */ - public GHCommitQueryBuilder queryCommits() { - return new GHCommitQueryBuilder(this); - } - - /** - * Retrieves issues. + * Gets a workflow by id. * - * @return the gh issue query builder + * @param id + * the id of the workflow run + * @return the workflow run + * @throws IOException + * the io exception */ - public GHIssueQueryBuilder.ForRepository queryIssues() { - return new GHIssueQueryBuilder.ForRepository(this); + public GHWorkflow getWorkflow(long id) throws IOException { + return getWorkflow(String.valueOf(id)); } /** - * Retrieves pull requests. + * Gets a workflow by name of the file. * - * @return the gh pull request query builder + * @param nameOrId + * either the name of the file (e.g. my-workflow.yml) or the id as a string + * @return the workflow run + * @throws IOException + * the io exception */ - public GHPullRequestQueryBuilder queryPullRequests() { - return new GHPullRequestQueryBuilder(this); + public GHWorkflow getWorkflow(String nameOrId) throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("actions/workflows"), nameOrId) + .fetch(GHWorkflow.class) + .wrapUp(this); } /** @@ -2996,427 +3008,371 @@ public GHWorkflowRunQueryBuilder queryWorkflowRuns() { } /** - * Read an autolink by ID. - * (https://docs.github.com/en/rest/repos/autolinks?apiVersion=2022-11-28#get-an-autolink-reference-of-a-repository) + * Gets a workflow run. * - * @param autolinkId - * the autolink id - * @return the autolink + * @param id + * the id of the workflow run + * @return the workflow run * @throws IOException * the io exception */ - public GHAutolink readAutolink(int autolinkId) throws IOException { + public GHWorkflowRun getWorkflowRun(long id) throws IOException { return root().createRequest() - .withHeader("Accept", "application/vnd.github+json") - .withUrlPath(String.format("/repos/%s/%s/autolinks/%d", getOwnerName(), getName(), autolinkId)) - .fetch(GHAutolink.class) - .lateBind(this); + .withUrlPath(getApiTailUrl("actions/runs"), String.valueOf(id)) + .fetch(GHWorkflowRun.class) + .wrapUp(this); } /** - * Reads the content of a blob as a stream for better efficiency. + * Lists all the artifacts of this repository. * - * @param blobSha - * the blob sha - * @return the input stream - * @throws IOException - * the io exception - * @see Get a blob - * @see #getBlob(String) #getBlob(String) + * @return the paged iterable */ - public InputStream readBlob(String blobSha) throws IOException { - String target = getApiTailUrl("git/blobs/" + blobSha); - - // https://developer.github.com/v3/media/ describes this media type - return root().createRequest() - .withHeader("Accept", "application/vnd.github.raw") - .withUrlPath(target) - .fetchStream(Requester::copyInputStream); + public PagedIterable listArtifacts() { + return new GHArtifactsIterable(this, root().createRequest().withUrlPath(getApiTailUrl("actions/artifacts"))); } /** - * Streams a tar archive of the repository, optionally at a given ref. + * Gets an artifact by id. * - * @param - * the type of result - * @param streamFunction - * The {@link InputStreamFunction} that will process the stream - * @param ref - * if null the repository's default branch, usually main, - * @return the result of reading the stream. + * @param id + * the id of the artifact + * @return the artifact * @throws IOException - * The IO exception. + * the io exception */ - public T readTar(InputStreamFunction streamFunction, String ref) throws IOException { - return downloadArchive("tar", ref, streamFunction); + public GHArtifact getArtifact(long id) throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("actions/artifacts"), String.valueOf(id)) + .fetch(GHArtifact.class) + .wrapUp(this); } /** - * Streams a zip archive of the repository, optionally at a given ref. + * Gets a job from a workflow run by id. * - * @param - * the type of result - * @param streamFunction - * The {@link InputStreamFunction} that will process the stream - * @param ref - * if null the repository's default branch, usually main, - * @return the result of reading the stream. + * @param id + * the id of the job + * @return the job * @throws IOException - * The IO exception. + * the io exception */ - public T readZip(InputStreamFunction streamFunction, String ref) throws IOException { - return downloadArchive("zip", ref, streamFunction); + public GHWorkflowJob getWorkflowJob(long id) throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("/actions/jobs"), String.valueOf(id)) + .fetch(GHWorkflowJob.class) + .wrapUp(this); } /** - * Remove collaborators. + * Gets the public key for the given repo. * - * @param users - * the users + * @return the public key * @throws IOException * the io exception */ - public void removeCollaborators(Collection users) throws IOException { - modifyCollaborators(users, "DELETE", null); + public GHRepositoryPublicKey getPublicKey() throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("/actions/secrets/public-key")) + .fetch(GHRepositoryPublicKey.class) + .wrapUp(this); } - /** - * Remove collaborators. - * - * @param users - * the users - * @throws IOException - * the io exception - */ - public void removeCollaborators(GHUser... users) throws IOException { - removeCollaborators(asList(users)); + // Only used within listTopics(). + private static class Topics { + public List names; } /** - * Rename this repository. + * Return the topics for this repository. See + * https://developer.github.com/v3/repos/#list-all-topics-for-a-repository * - * @param name - * the name + * @return the list * @throws IOException * the io exception */ - public void renameTo(String name) throws IOException { - set().name(name); + public List listTopics() throws IOException { + Topics topics = root().createRequest().withUrlPath(getApiTailUrl("topics")).fetch(Topics.class); + return topics.names; } /** - * Render a Markdown document. - *

- * In {@linkplain MarkdownMode#GFM GFM mode}, issue numbers and user mentions are linked accordingly. + * Set the topics for this repository. See + * https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository * - * @param text - * the text - * @param mode - * the mode - * @return the reader + * @param topics + * the topics * @throws IOException * the io exception - * @see GitHub#renderMarkdown(String) GitHub#renderMarkdown(String) - */ - public Reader renderMarkdown(String text, MarkdownMode mode) throws IOException { - return new InputStreamReader( - root().createRequest() - .method("POST") - .with("text", text) - .with("mode", mode == null ? null : mode.toString()) - .with("context", getFullName()) - .withUrlPath("/markdown") - .fetchStream(Requester::copyInputStream), - "UTF-8"); - } - - /** - * Retrieves pull requests according to search terms. - * - * @return gh pull request search builder for current repository */ - public GHPullRequestSearchBuilder searchPullRequests() { - return new GHPullRequestSearchBuilder(this.root()).repo(this); + public void setTopics(List topics) throws IOException { + root().createRequest().method("PUT").with("names", topics).withUrlPath(getApiTailUrl("topics")).send(); } /** - * Creates a builder that can be used to bulk update repository settings. + * Set/Update a repository secret + * "https://docs.github.com/rest/reference/actions#create-or-update-a-repository-secret" * - * @return the repository updater + * @param secretName + * the name of the secret + * @param encryptedValue + * The encrypted value for this secret + * @param publicKeyId + * The id of the Public Key used to encrypt this secret + * @throws IOException + * the io exception */ - public Setter set() { - return new Setter(this); + public void createSecret(String secretName, String encryptedValue, String publicKeyId) throws IOException { + root().createRequest() + .method("PUT") + .with("encrypted_value", encryptedValue) + .with("key_id", publicKeyId) + .withUrlPath(getApiTailUrl("actions/secrets") + "/" + secretName) + .send(); } /** - * Sets {@link #getCompare(String, String)} to return a {@link GHCompare} that uses a paginated commit list instead - * of limiting to 250 results. - * - * By default, {@link GHCompare} returns all commits in the comparison as part of the request, limited to 250 - * results. More recently GitHub added the ability to return the commits as a paginated query allowing for more than - * 250 results. + * Create a tag. See https://developer.github.com/v3/git/tags/#create-a-tag-object * - * @param value - * true if you want commits returned in paginated form. + * @param tag + * The tag's name. + * @param message + * The tag message. + * @param object + * The SHA of the git object this is tagging. + * @param type + * The type of the object we're tagging: "commit", "tree" or "blob". + * @return The newly created tag. + * @throws IOException + * Signals that an I/O exception has occurred. */ - public void setCompareUsePaginatedCommits(boolean value) { - compareUsePaginatedCommits = value; + public GHTagObject createTag(String tag, String message, String object, String type) throws IOException { + return root().createRequest() + .method("POST") + .with("tag", tag) + .with("message", message) + .with("object", object) + .with("type", type) + .withUrlPath(getApiTailUrl("git/tags")) + .fetch(GHTagObject.class) + .wrap(this); } /** - * Sets default branch. + * Streams a zip archive of the repository, optionally at a given ref. * - * @param value - * the value + * @param + * the type of result + * @param streamFunction + * The {@link InputStreamFunction} that will process the stream + * @param ref + * if null the repository's default branch, usually main, + * @return the result of reading the stream. * @throws IOException - * the io exception + * The IO exception. */ - public void setDefaultBranch(String value) throws IOException { - set().defaultBranch(value); + public T readZip(InputStreamFunction streamFunction, String ref) throws IOException { + return downloadArchive("zip", ref, streamFunction); } /** - * Sets description. + * Streams a tar archive of the repository, optionally at a given ref. * - * @param value - * the value + * @param + * the type of result + * @param streamFunction + * The {@link InputStreamFunction} that will process the stream + * @param ref + * if null the repository's default branch, usually main, + * @return the result of reading the stream. * @throws IOException - * the io exception + * The IO exception. */ - public void setDescription(String value) throws IOException { - set().description(value); + public T readTar(InputStreamFunction streamFunction, String ref) throws IOException { + return downloadArchive("tar", ref, streamFunction); } /** - * Sets email service hook. + * Create a repository dispatch event, which can be used to start a workflow/action from outside github, as + * described on https://docs.github.com/en/rest/reference/repos#create-a-repository-dispatch-event * - * @param address - * the address + * @param + * type of client payload + * @param eventType + * the eventType + * @param clientPayload + * a custom payload , can be nullable * @throws IOException * the io exception */ - public void setEmailServiceHook(String address) throws IOException { - Map config = new HashMap<>(); - config.put("address", address); + public void dispatch(String eventType, @Nullable T clientPayload) throws IOException { root().createRequest() .method("POST") - .with("name", "email") - .with("config", config) - .with("active", true) - .withUrlPath(getApiTailUrl("hooks")) + .withUrlPath(getApiTailUrl("dispatches")) + .with("event_type", eventType) + .with("client_payload", clientPayload) .send(); } + private T downloadArchive(@Nonnull String type, + @CheckForNull String ref, + @Nonnull InputStreamFunction streamFunction) throws IOException { + requireNonNull(streamFunction, "Sink must not be null"); + String tailUrl = getApiTailUrl(type + "ball"); + if (ref != null) { + tailUrl += "/" + ref; + } + final Requester builder = root().createRequest().method("GET").withUrlPath(tailUrl); + return builder.fetchStream(streamFunction); + } + /** - * Sets homepage. + * Populate this object. * - * @param value - * the value * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public void setHomepage(String value) throws IOException { - set().homepage(value); + void populate() throws IOException { + if (isOffline()) { + return; // can't populate if the root is offline + } + + // We don't use the URL provided in the JSON because it is not reliable: + // 1. There is bug in Push event payloads that returns the wrong url. + // For Push event repository records, they take the form + // "https://github.com/{fullName}". + // All other occurrences of "url" take the form "https://api.github.com/...". + // 2. For Installation event payloads, the URL is not provided at all. + root().createRequest().withUrlPath(getApiTailUrl("")).fetchInto(this); } /** - * Sets private. + * A {@link GHRepositoryBuilder} that allows multiple properties to be updated per request. * - * @param value - * the value - * @throws IOException - * the io exception + * Consumer must call {@link #done()} to commit changes. */ - public void setPrivate(boolean value) throws IOException { - set().private_(value); + @BetaApi + public static class Updater extends GHRepositoryBuilder { + + /** + * Instantiates a new updater. + * + * @param repository + * the repository + */ + protected Updater(@Nonnull GHRepository repository) { + super(Updater.class, repository.root(), null); + // even when we don't change the name, we need to send it in + // this requirement may be out-of-date, but we do not want to break it + requester.with("name", repository.name); + + requester.method("PATCH").withUrlPath(repository.getApiTailUrl("")); + } } /** - * Set the topics for this repository. See - * https://developer.github.com/v3/repos/#replace-all-topics-for-a-repository + * Star a repository. * - * @param topics - * the topics * @throws IOException * the io exception */ - public void setTopics(List topics) throws IOException { - root().createRequest().method("PUT").with("names", topics).withUrlPath(getApiTailUrl("topics")).send(); + public void star() throws IOException { + root().createRequest().method("PUT").withUrlPath(String.format("/user/starred/%s", full_name)).send(); } /** - * Sets visibility. + * Unstar a repository. * - * @param value - * the value * @throws IOException * the io exception */ - public void setVisibility(final Visibility value) throws IOException { - root().createRequest() - .method("PATCH") - .with("name", name) - .with("visibility", value) - .withUrlPath(getApiTailUrl("")) - .send(); + public void unstar() throws IOException { + root().createRequest().method("DELETE").withUrlPath(String.format("/user/starred/%s", full_name)).send(); } /** - * Star a repository. + * Get the top 10 popular contents over the last 14 days as described on + * https://docs.github.com/en/rest/metrics/traffic?apiVersion=2022-11-28#get-top-referral-paths * + * @return list of top referral paths * @throws IOException * the io exception */ - public void star() throws IOException { - root().createRequest().method("PUT").withUrlPath(String.format("/user/starred/%s", fullName)).send(); + public List getTopReferralPaths() throws IOException { + return Arrays.asList(root().createRequest() + .method("GET") + .withUrlPath(getApiTailUrl("/traffic/popular/paths")) + .fetch(GHRepositoryTrafficTopReferralPath[].class)); } /** - * Subscribes to this repository to get notifications. + * Get the top 10 referrers over the last 14 days as described on + * https://docs.github.com/en/rest/metrics/traffic?apiVersion=2022-11-28#get-top-referral-sources * - * @param subscribed - * the subscribed - * @param ignored - * the ignored - * @return the gh subscription + * @return list of top referrers * @throws IOException * the io exception */ - public GHSubscription subscribe(boolean subscribed, boolean ignored) throws IOException { - return root().createRequest() - .method("PUT") - .with("subscribed", subscribed) - .with("ignored", ignored) - .withUrlPath(getApiTailUrl("subscription")) - .fetch(GHSubscription.class) - .wrapUp(this); + public List getTopReferralSources() throws IOException { + return Arrays.asList(root().createRequest() + .method("GET") + .withUrlPath(getApiTailUrl("/traffic/popular/referrers")) + .fetch(GHRepositoryTrafficTopReferralSources[].class)); } /** - * Sync this repository fork branch + * Get all active rules that apply to the specified branch + * (https://docs.github.com/en/rest/repos/rules?apiVersion=2022-11-28#get-rules-for-a-branch). * * @param branch - * the branch to sync - * @return The current repository + * the branch + * @return the rules for branch * @throws IOException * the io exception */ - public GHBranchSync sync(String branch) throws IOException { + public PagedIterable listRulesForBranch(String branch) throws IOException { return root().createRequest() - .method("POST") - .with("branch", branch) - .withUrlPath(getApiTailUrl("merge-upstream")) - .fetch(GHBranchSync.class) - .wrap(this); + .method("GET") + .withUrlPath(getApiTailUrl("/rules/branches/" + branch)) + .toIterable(GHRepositoryRule[].class, null); } /** - * Unstar a repository. + * Check, if vulnerability alerts are enabled for this repository + * (https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#check-if-vulnerability-alerts-are-enabled-for-a-repository). * + * @return true, if vulnerability alerts are enabled * @throws IOException * the io exception */ - public void unstar() throws IOException { - root().createRequest().method("DELETE").withUrlPath(String.format("/user/starred/%s", fullName)).send(); - } - - /** - * Creates a builder that can be used to bulk update repository settings. - * - * @return the repository updater - */ - public Updater update() { - return new Updater(this); + public boolean isVulnerabilityAlertsEnabled() throws IOException { + return root().createRequest() + .method("GET") + .withUrlPath(getApiTailUrl("/vulnerability-alerts")) + .fetchHttpStatusCode() == 204; } /** - * Updates an existing check run. + * A {@link GHRepositoryBuilder} that allows multiple properties to be updated per request. * - * @param checkId - * the existing checkId - * @return a builder which you should customize, then call {@link GHCheckRunBuilder#create} + * Consumer must call {@link #done()} to commit changes. */ - public @NonNull GHCheckRunBuilder updateCheckRun(long checkId) { - return new GHCheckRunBuilder(this, checkId); - } - - private T downloadArchive(@Nonnull String type, - @CheckForNull String ref, - @Nonnull InputStreamFunction streamFunction) throws IOException { - requireNonNull(streamFunction, "Sink must not be null"); - String tailUrl = getApiTailUrl(type + "ball"); - if (ref != null) { - tailUrl += "/" + ref; - } - final Requester builder = root().createRequest().method("GET").withUrlPath(tailUrl); - return builder.fetchStream(streamFunction); - } - - private GHContentWithLicense getLicenseContent_() throws IOException { - try { - return root().createRequest() - .withUrlPath(getApiTailUrl("license")) - .fetch(GHContentWithLicense.class) - .wrap(this); - } catch (FileNotFoundException e) { - return null; - } - } - - private PagedIterable listUsers(Requester requester, final String suffix) { - return requester.withUrlPath(getApiTailUrl(suffix)).toIterable(GHUser[].class, null); - } - - private PagedIterable listUsers(final String suffix) { - return listUsers(root().createRequest(), suffix); - } - - private void modifyCollaborators(@NonNull Collection users, - @NonNull String method, - @CheckForNull GHOrganization.RepositoryRole permission) throws IOException { - Requester requester = root().createRequest().method(method); - if (permission != null) { - requester = requester.with("permission", permission.toString()).inBody(); - } - - // Make sure that the users collection doesn't have any duplicates - for (GHUser user : new LinkedHashSet<>(users)) { - requester.withUrlPath(getApiTailUrl("collaborators/" + user.getLogin())).send(); - } - } + @BetaApi + public static class Setter extends GHRepositoryBuilder { - /** - * Gets the api tail url. - * - * @param tail - * the tail - * @return the api tail url - */ - String getApiTailUrl(String tail) { - if (tail.length() > 0 && !tail.startsWith("/")) { - tail = '/' + tail; - } - return "/repos/" + fullName + tail; - } + /** + * Instantiates a new setter. + * + * @param repository + * the repository + */ + protected Setter(@Nonnull GHRepository repository) { + super(GHRepository.class, repository.root(), null); + // even when we don't change the name, we need to send it in + // this requirement may be out-of-date, but we do not want to break it + requester.with("name", repository.name); - /** - * Populate this object. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - void populate() throws IOException { - if (isOffline()) { - return; // can't populate if the root is offline + requester.method("PATCH").withUrlPath(repository.getApiTailUrl("")); } - - // We don't use the URL provided in the JSON because it is not reliable: - // 1. There is bug in Push event payloads that returns the wrong url. - // For Push event repository records, they take the form - // "https://github.com/{fullName}". - // All other occurrences of "url" take the form "https://api.github.com/...". - // 2. For Installation event payloads, the URL is not provided at all. - root().createRequest().withUrlPath(getApiTailUrl("")).fetchInto(this); } - } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryBuilder.java b/src/main/java/org/kohsuke/github/GHRepositoryBuilder.java index 02bcba2d1d..d32dbd2563 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryBuilder.java @@ -29,16 +29,18 @@ protected GHRepositoryBuilder(Class intermediateReturnType, GitHub root, GHRe } /** - * Allow or disallow private forks + * Allow or disallow squash-merging pull requests. * * @param enabled * true if enabled + * * @return a builder to continue with building + * * @throws IOException * In case of any networking error or error from the server. */ - public S allowForking(boolean enabled) throws IOException { - return with("allow_forking", enabled); + public S allowSquashMerge(boolean enabled) throws IOException { + return with("allow_squash_merge", enabled); } /** @@ -72,31 +74,16 @@ public S allowRebaseMerge(boolean enabled) throws IOException { } /** - * Allow or disallow squash-merging pull requests. + * Allow or disallow private forks * * @param enabled * true if enabled - * * @return a builder to continue with building - * * @throws IOException * In case of any networking error or error from the server. */ - public S allowSquashMerge(boolean enabled) throws IOException { - return with("allow_squash_merge", enabled); - } - - /** - * Default repository branch. - * - * @param branch - * branch name - * @return a builder to continue with building - * @throws IOException - * In case of any networking error or error from the server. - */ - public S defaultBranch(String branch) throws IOException { - return with("default_branch", branch); + public S allowForking(boolean enabled) throws IOException { + return with("allow_forking", enabled); } /** @@ -115,41 +102,42 @@ public S deleteBranchOnMerge(boolean enabled) throws IOException { } /** - * Description for repository. + * Default repository branch. * - * @param description - * description of repository + * @param branch + * branch name * @return a builder to continue with building * @throws IOException * In case of any networking error or error from the server. */ - public S description(String description) throws IOException { - return with("description", description); + public S defaultBranch(String branch) throws IOException { + return with("default_branch", branch); } /** - * Done. + * Description for repository. * - * @return the GH repository + * @param description + * description of repository + * @return a builder to continue with building * @throws IOException - * Signals that an I/O exception has occurred. + * In case of any networking error or error from the server. */ - @Override - public GHRepository done() throws IOException { - return super.done(); + public S description(String description) throws IOException { + return with("description", description); } /** - * Enables downloads. + * Homepage for repository. * - * @param enabled - * true if enabled + * @param homepage + * homepage of repository * @return a builder to continue with building * @throws IOException * In case of any networking error or error from the server. */ - public S downloads(boolean enabled) throws IOException { - return with("has_downloads", enabled); + public S homepage(URL homepage) throws IOException { + return homepage(homepage.toExternalForm()); } /** @@ -166,29 +154,29 @@ public S homepage(String homepage) throws IOException { } /** - * Homepage for repository. + * Sets the repository to private. * - * @param homepage - * homepage of repository + * @param enabled + * private if true * @return a builder to continue with building * @throws IOException * In case of any networking error or error from the server. */ - public S homepage(URL homepage) throws IOException { - return homepage(homepage.toExternalForm()); + public S private_(boolean enabled) throws IOException { + return with("private", enabled); } /** - * Specifies whether the repository is a template. + * Sets the repository visibility. * - * @param enabled - * true if enabled + * @param visibility + * visibility of repository * @return a builder to continue with building * @throws IOException * In case of any networking error or error from the server. */ - public S isTemplate(boolean enabled) throws IOException { - return with("is_template", enabled); + public S visibility(final Visibility visibility) throws IOException { + return with("visibility", visibility.toString()); } /** @@ -205,20 +193,20 @@ public S issues(boolean enabled) throws IOException { } /** - * Sets the repository to private. + * Enables projects. * * @param enabled - * private if true + * true if enabled * @return a builder to continue with building * @throws IOException * In case of any networking error or error from the server. */ - public S private_(boolean enabled) throws IOException { - return with("private", enabled); + public S projects(boolean enabled) throws IOException { + return with("has_projects", enabled); } /** - * Enables projects. + * Enables wiki. * * @param enabled * true if enabled @@ -226,25 +214,25 @@ public S private_(boolean enabled) throws IOException { * @throws IOException * In case of any networking error or error from the server. */ - public S projects(boolean enabled) throws IOException { - return with("has_projects", enabled); + public S wiki(boolean enabled) throws IOException { + return with("has_wiki", enabled); } /** - * Sets the repository visibility. + * Enables downloads. * - * @param visibility - * visibility of repository + * @param enabled + * true if enabled * @return a builder to continue with building * @throws IOException * In case of any networking error or error from the server. */ - public S visibility(final Visibility visibility) throws IOException { - return with("visibility", visibility.toString()); + public S downloads(boolean enabled) throws IOException { + return with("has_downloads", enabled); } /** - * Enables wiki. + * Specifies whether the repository is a template. * * @param enabled * true if enabled @@ -252,8 +240,20 @@ public S visibility(final Visibility visibility) throws IOException { * @throws IOException * In case of any networking error or error from the server. */ - public S wiki(boolean enabled) throws IOException { - return with("has_wiki", enabled); + public S isTemplate(boolean enabled) throws IOException { + return with("is_template", enabled); + } + + /** + * Done. + * + * @return the GH repository + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Override + public GHRepository done() throws IOException { + return super.done(); } /** diff --git a/src/main/java/org/kohsuke/github/GHRepositoryChanges.java b/src/main/java/org/kohsuke/github/GHRepositoryChanges.java index c640ba2dc7..c3792f1819 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryChanges.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryChanges.java @@ -9,24 +9,42 @@ public class GHRepositoryChanges { /** - * Repository name that was changed. + * Create default GHRepositoryChanges instance */ - public static class FromName { + public GHRepositoryChanges() { + } - private String from; + private FromRepository repository; + private Owner owner; + + /** + * Get outer owner object. + * + * @return Owner + */ + public Owner getOwner() { + return owner; + } + + /** + * Outer object of owner from whom this repository was transferred. + */ + public static class Owner { /** - * Create default FromName instance + * Create default Owner instance */ - public FromName() { + public Owner() { } + private FromOwner from; + /** - * Get previous name of the repository before rename. + * Get in owner object. * - * @return String + * @return FromOwner */ - public String getFrom() { + public FromOwner getFrom() { return from; } } @@ -36,48 +54,58 @@ public String getFrom() { */ public static class FromOwner { - private GHOrganization organization; - - private GHUser user; /** * Create default FromOwner instance */ public FromOwner() { } + private GHUser user; + private GHOrganization organization; + /** - * Get organization from which this repository was transferred. + * Get user from which this repository was transferred. * - * @return GHOrganization + * @return user */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHOrganization getOrganization() { - return organization; + public GHUser getUser() { + return user; } /** - * Get user from which this repository was transferred. + * Get organization from which this repository was transferred. * - * @return user + * @return GHOrganization */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHUser getUser() { - return user; + public GHOrganization getOrganization() { + return organization; } } + + /** + * Get repository. + * + * @return FromRepository + */ + public FromRepository getRepository() { + return repository; + } + /** * Repository object from which the name was changed. */ public static class FromRepository { - private FromName name; - /** * Create default FromRepository instance */ public FromRepository() { } + private FromName name; + /** * Get top level object for the previous name of the repository. * @@ -89,53 +117,25 @@ public FromName getName() { } /** - * Outer object of owner from whom this repository was transferred. + * Repository name that was changed. */ - public static class Owner { - - private FromOwner from; + public static class FromName { /** - * Create default Owner instance + * Create default FromName instance */ - public Owner() { + public FromName() { } + private String from; + /** - * Get in owner object. + * Get previous name of the repository before rename. * - * @return FromOwner + * @return String */ - public FromOwner getFrom() { + public String getFrom() { return from; } } - - private Owner owner; - - private FromRepository repository; - - /** - * Create default GHRepositoryChanges instance - */ - public GHRepositoryChanges() { - } - - /** - * Get outer owner object. - * - * @return Owner - */ - public Owner getOwner() { - return owner; - } - - /** - * Get repository. - * - * @return FromRepository - */ - public FromRepository getRepository() { - return repository; - } } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java b/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java index 356a6667b7..6d7bf15140 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java @@ -10,32 +10,6 @@ * @see GHRepository#getCloneTraffic() GHRepository#getCloneTraffic() */ public class GHRepositoryCloneTraffic extends GHRepositoryTraffic { - /** - * The type DailyInfo. - */ - public static class DailyInfo extends GHRepositoryTraffic.DailyInfo { - - /** - * Instantiates a new daily info. - */ - DailyInfo() { - } - - /** - * Instantiates a new daily info. - * - * @param timestamp - * the timestamp - * @param count - * the count - * @param uniques - * the uniques - */ - DailyInfo(String timestamp, int count, int uniques) { - super(timestamp, count, uniques); - } - } - private List clones; /** @@ -76,4 +50,30 @@ public List getClones() { public List getDailyInfo() { return getClones(); } + + /** + * The type DailyInfo. + */ + public static class DailyInfo extends GHRepositoryTraffic.DailyInfo { + + /** + * Instantiates a new daily info. + */ + DailyInfo() { + } + + /** + * Instantiates a new daily info. + * + * @param timestamp + * the timestamp + * @param count + * the count + * @param uniques + * the uniques + */ + DailyInfo(String timestamp, int count, int uniques) { + super(timestamp, count, uniques); + } + } } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryDiscussion.java b/src/main/java/org/kohsuke/github/GHRepositoryDiscussion.java index f319d1f7cd..2c1bc4b27a 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryDiscussion.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryDiscussion.java @@ -1,10 +1,9 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import org.kohsuke.github.internal.EnumUtils; +import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -24,172 +23,46 @@ public class GHRepositoryDiscussion extends GHObject { /** - * Category of a discussion. - *

- * Note that while it is relatively close to the GraphQL objects, some of the fields such as the id are handled - * differently. - * - * @see The - * GraphQL API for Discussions + * Create default GHRepositoryDiscussion instance */ - public static class Category extends GitHubBridgeAdapterObject { - - private String createdAt; - - private String description; - private String emoji; - private long id; - private boolean isAnswerable; - private String name; - private String nodeId; - private long repositoryId; - private String slug; - private String updatedAt; - /** - * Create default Category instance - */ - public Category() { - } - - /** - * Gets the created at. - * - * @return the created at - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCreatedAt() { - return GitHubClient.parseInstant(createdAt); - } - - /** - * Gets the description. - * - * @return the description - */ - public String getDescription() { - return description; - } - - /** - * Gets the emoji. - * - * @return the emoji - */ - public String getEmoji() { - return emoji; - } - - /** - * Gets the id. - * - * @return the id - */ - public long getId() { - return id; - } - - /** - * Gets the name. - * - * @return the name - */ - public String getName() { - return name; - } - - /** - * Gets the node id. - * - * @return the node id - */ - public String getNodeId() { - return nodeId; - } - - /** - * Gets the repository id. - * - * @return the repository id - */ - public long getRepositoryId() { - return repositoryId; - } - - /** - * Gets the slug. - * - * @return the slug - */ - public String getSlug() { - return slug; - } - - /** - * Gets the updated at. - * - * @return the updated at - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getUpdatedAt() { - return GitHubClient.parseInstant(updatedAt); - } - - /** - * Checks if is answerable. - * - * @return true, if is answerable - */ - public boolean isAnswerable() { - return isAnswerable; - } + public GHRepositoryDiscussion() { } - /** - * The Enum State. - */ - public enum State { - - /** The locked. */ - LOCKED, - /** The open. */ - OPEN, - /** The unknown. */ - UNKNOWN; - } + private Category category; - private String activeLockReason; + private String answerHtmlUrl; private String answerChosenAt; private GHUser answerChosenBy; - private String answerHtmlUrl; - - private GHCommentAuthorAssociation authorAssociation; - private String body; - private Category category; - private int comments; private String htmlUrl; - private boolean locked; + private int number; - private String state; - private String timelineUrl; private String title; - private GHUser user; + private String state; + private boolean locked; + private int comments; + private GHCommentAuthorAssociation authorAssociation; + private String activeLockReason; + private String body; + private String timelineUrl; /** - * Create default GHRepositoryDiscussion instance + * Gets the category. + * + * @return the category */ - public GHRepositoryDiscussion() { + public Category getCategory() { + return category; } /** - * Gets the active lock reason. + * Gets the answer html url. * - * @return the active lock reason + * @return the answer html url */ - public String getActiveLockReason() { - return activeLockReason; + public URL getAnswerHtmlUrl() { + return GitHubClient.parseURL(answerHtmlUrl); } /** @@ -197,54 +70,75 @@ public String getActiveLockReason() { * * @return the answer chosen at */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getAnswerChosenAt() { - return GitHubClient.parseInstant(answerChosenAt); + public Date getAnswerChosenAt() { + return GitHubClient.parseDate(answerChosenAt); } /** * Gets the answer chosen by. * * @return the answer chosen by + * @throws IOException + * Signals that an I/O exception has occurred. */ - public GHUser getAnswerChosenBy() { + public GHUser getAnswerChosenBy() throws IOException { return root().intern(answerChosenBy); } /** - * Gets the answer html url. + * Gets the html url. * - * @return the answer html url + * @return the html url */ - public URL getAnswerHtmlUrl() { - return GitHubClient.parseURL(answerHtmlUrl); + public URL getHtmlUrl() { + return GitHubClient.parseURL(htmlUrl); } /** - * Gets the author association. + * Gets the number. * - * @return the author association + * @return the number */ - public GHCommentAuthorAssociation getAuthorAssociation() { - return authorAssociation; + public int getNumber() { + return number; } /** - * Gets the body. + * Gets the title. * - * @return the body + * @return the title */ - public String getBody() { - return body; + public String getTitle() { + return title; } /** - * Gets the category. + * Gets the user. * - * @return the category + * @return the user + * @throws IOException + * Signals that an I/O exception has occurred. */ - public Category getCategory() { - return category; + public GHUser getUser() throws IOException { + return root().intern(user); + } + + /** + * Gets the state. + * + * @return the state + */ + public State getState() { + return EnumUtils.getEnumOrDefault(State.class, state, State.UNKNOWN); + } + + /** + * Checks if is locked. + * + * @return true, if is locked + */ + public boolean isLocked() { + return locked; } /** @@ -257,30 +151,30 @@ public int getComments() { } /** - * Gets the html url. + * Gets the author association. * - * @return the html url + * @return the author association */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public GHCommentAuthorAssociation getAuthorAssociation() { + return authorAssociation; } /** - * Gets the number. + * Gets the active lock reason. * - * @return the number + * @return the active lock reason */ - public int getNumber() { - return number; + public String getActiveLockReason() { + return activeLockReason; } /** - * Gets the state. + * Gets the body. * - * @return the state + * @return the body */ - public State getState() { - return EnumUtils.getEnumOrDefault(State.class, state, State.UNKNOWN); + public String getBody() { + return body; } /** @@ -293,29 +187,135 @@ public String getTimelineUrl() { } /** - * Gets the title. + * Category of a discussion. + *

+ * Note that while it is relatively close to the GraphQL objects, some of the fields such as the id are handled + * differently. * - * @return the title + * @see The + * GraphQL API for Discussions */ - public String getTitle() { - return title; - } + public static class Category { - /** - * Gets the user. - * - * @return the user - */ - public GHUser getUser() { - return root().intern(user); + /** + * Create default Category instance + */ + public Category() { + } + + private long id; + private String nodeId; + private long repositoryId; + private String emoji; + private String name; + private String description; + private String createdAt; + private String updatedAt; + private String slug; + private boolean isAnswerable; + + /** + * Gets the id. + * + * @return the id + */ + public long getId() { + return id; + } + + /** + * Gets the node id. + * + * @return the node id + */ + public String getNodeId() { + return nodeId; + } + + /** + * Gets the repository id. + * + * @return the repository id + */ + public long getRepositoryId() { + return repositoryId; + } + + /** + * Gets the emoji. + * + * @return the emoji + */ + public String getEmoji() { + return emoji; + } + + /** + * Gets the name. + * + * @return the name + */ + public String getName() { + return name; + } + + /** + * Gets the description. + * + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * Gets the created at. + * + * @return the created at + */ + public Date getCreatedAt() { + return GitHubClient.parseDate(createdAt); + } + + /** + * Gets the updated at. + * + * @return the updated at + */ + public Date getUpdatedAt() { + return GitHubClient.parseDate(updatedAt); + } + + /** + * Gets the slug. + * + * @return the slug + */ + public String getSlug() { + return slug; + } + + /** + * Checks if is answerable. + * + * @return true, if is answerable + */ + public boolean isAnswerable() { + return isAnswerable; + } } /** - * Checks if is locked. - * - * @return true, if is locked + * The Enum State. */ - public boolean isLocked() { - return locked; + public enum State { + + /** The open. */ + OPEN, + /** The locked. */ + LOCKED, + /** The unknown. */ + UNKNOWN; } } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryDiscussionComment.java b/src/main/java/org/kohsuke/github/GHRepositoryDiscussionComment.java index b951491149..b16f61a98b 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryDiscussionComment.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryDiscussionComment.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import java.io.IOException; import java.net.URL; /** @@ -17,37 +18,37 @@ */ public class GHRepositoryDiscussionComment extends GHObject { - private GHCommentAuthorAssociation authorAssociation; - - private String body; - - private int childCommentCount; - private String htmlUrl; - - private Long parentId; - private GHUser user; /** * Create default GHRepositoryDiscussionComment instance */ public GHRepositoryDiscussionComment() { } + private String htmlUrl; + + private Long parentId; + private int childCommentCount; + + private GHUser user; + private GHCommentAuthorAssociation authorAssociation; + private String body; + /** - * Gets the author association. + * Gets the html url. * - * @return the author association + * @return the html url */ - public GHCommentAuthorAssociation getAuthorAssociation() { - return authorAssociation; + public URL getHtmlUrl() { + return GitHubClient.parseURL(htmlUrl); } /** - * Gets the body. + * Gets the parent comment id. * - * @return the body + * @return the parent comment id */ - public String getBody() { - return body; + public Long getParentId() { + return parentId; } /** @@ -60,29 +61,31 @@ public int getChildCommentCount() { } /** - * Gets the html url. + * Gets the user. * - * @return the html url + * @return the user + * @throws IOException + * Signals that an I/O exception has occurred. */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public GHUser getUser() throws IOException { + return root().intern(user); } /** - * Gets the parent comment id. + * Gets the author association. * - * @return the parent comment id + * @return the author association */ - public Long getParentId() { - return parentId; + public GHCommentAuthorAssociation getAuthorAssociation() { + return authorAssociation; } /** - * Gets the user. + * Gets the body. * - * @return the user + * @return the body */ - public GHUser getUser() { - return root().intern(user); + public String getBody() { + return body; } } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryForkBuilder.java b/src/main/java/org/kohsuke/github/GHRepositoryForkBuilder.java deleted file mode 100644 index 8d8d5db4c5..0000000000 --- a/src/main/java/org/kohsuke/github/GHRepositoryForkBuilder.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.kohsuke.github; - -import java.io.IOException; -import java.io.InterruptedIOException; - -/** - * A builder pattern object for creating a fork of a repository. - * - * @see GHRepository#createFork() GHRepository#createFork()GHRepository#createFork() - * @see Repository fork API - */ -public class GHRepositoryForkBuilder { - static int FORK_RETRY_INTERVAL = 3000; - private Boolean defaultBranchOnly; - private String name; - private String organization; - private final GHRepository repo; - - private final Requester req; - - /** - * Instantiates a new Gh repository fork builder. - * - * @param repo - * the repository - */ - GHRepositoryForkBuilder(GHRepository repo) { - this.repo = repo; - this.req = repo.root().createRequest(); - } - - /** - * Creates the fork with the specified parameters. - * - * @return the gh repository - * @throws IOException - * the io exception - */ - public GHRepository create() throws IOException { - if (defaultBranchOnly != null) { - req.with("default_branch_only", defaultBranchOnly); - } - if (organization != null) { - req.with("organization", organization); - } - if (name != null) { - req.with("name", name); - } - - req.method("POST").withUrlPath(repo.getApiTailUrl("forks")).send(); - - // this API is asynchronous. we need to wait for a bit - for (int i = 0; i < 10; i++) { - GHRepository r = lookupForkedRepository(); - if (r != null) { - return r; - } - sleep(FORK_RETRY_INTERVAL); - } - throw new IOException(createTimeoutMessage()); - } - - /** - * Sets whether to fork only the default branch. - * - * @param defaultBranchOnly - * the default branch only - * @return the gh repository fork builder - */ - public GHRepositoryForkBuilder defaultBranchOnly(boolean defaultBranchOnly) { - this.defaultBranchOnly = defaultBranchOnly; - return this; - } - - /** - * Sets a custom name for the forked repository. - * - * @param name - * the desired repository name - * @return the builder - */ - public GHRepositoryForkBuilder name(String name) { - this.name = name; - return this; - } - - /** - * Specifies the target organization for the fork. - * - * @param organization - * the organization - * @return the gh repository fork builder - */ - public GHRepositoryForkBuilder organization(GHOrganization organization) { - this.organization = organization.getLogin(); - return this; - } - - private GHRepository lookupForkedRepository() throws IOException { - String repoName = name != null ? name : repo.getName(); - - if (organization != null) { - return repo.root().getOrganization(organization).getRepository(repoName); - } - return repo.root().getMyself().getRepository(repoName); - } - - /** - * Create timeout message string. - * - * @return the string - */ - String createTimeoutMessage() { - StringBuilder message = new StringBuilder(repo.getFullName()); - message.append(" was forked"); - - if (organization != null) { - message.append(" into ").append(organization); - } - - if (name != null) { - message.append(" with name ").append(name); - } - - message.append(" but can't find the new repository"); - return message.toString(); - } - - /** - * Sleep. - * - * @param millis - * the millis - * @throws IOException - * the io exception - */ - void sleep(int millis) throws IOException { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - throw (IOException) new InterruptedIOException().initCause(e); - } - } -} diff --git a/src/main/java/org/kohsuke/github/GHRepositoryPublicKey.java b/src/main/java/org/kohsuke/github/GHRepositoryPublicKey.java index a788907a53..843e67e872 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryPublicKey.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryPublicKey.java @@ -10,17 +10,26 @@ */ public class GHRepositoryPublicKey extends GHObject { - private String key; - - private String keyId; + /** + * Create default GHRepositoryPublicKey instance + */ + public GHRepositoryPublicKey() { + } // Not provided by the API. @JsonIgnore private GHRepository owner; + + private String keyId; + private String key; + /** - * Create default GHRepositoryPublicKey instance + * Gets the key id. + * + * @return the key id */ - public GHRepositoryPublicKey() { + public String getKeyId() { + return keyId; } /** @@ -32,15 +41,6 @@ public String getKey() { return key; } - /** - * Gets the key id. - * - * @return the key id - */ - public String getKeyId() { - return keyId; - } - /** * Wrap up. * diff --git a/src/main/java/org/kohsuke/github/GHRepositoryRule.java b/src/main/java/org/kohsuke/github/GHRepositoryRule.java index d348153e85..2db05c7057 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryRule.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryRule.java @@ -18,194 +18,183 @@ public class GHRepositoryRule extends GitHubInteractiveObject { /** - * Alerts threshold parameter. + * Create default GHRepositoryRule instance */ - public static enum AlertsThreshold { + public GHRepositoryRule() { + } + + private String type; + private String rulesetSourceType; + private String rulesetSource; + private long rulesetId; + private Map parameters; + + /** + * Gets the type. + * + * @return the type + */ + public Type getType() { + return EnumUtils.getEnumOrDefault(Type.class, this.type, Type.UNKNOWN); + } + + /** + * Gets the ruleset source type. + * + * @return the ruleset source type + */ + public RulesetSourceType getRulesetSourceType() { + return EnumUtils.getEnumOrDefault(RulesetSourceType.class, this.rulesetSourceType, RulesetSourceType.UNKNOWN); + } + + /** + * Gets the ruleset source. + * + * @return the ruleset source + */ + public String getRulesetSource() { + return this.rulesetSource; + } + + /** + * Gets the ruleset id. + * + * @return the ruleset id + */ + public long getRulesetId() { + return this.rulesetId; + } + + /** + * Gets a parameter. ({@link GHRepositoryRule.Parameters Parameters} provides a list of available parameters.) + * + * @param parameter + * the parameter + * @param + * the type of the parameter + * @return the parameters + * @throws IOException + * if an I/O error occurs + */ + public Optional getParameter(Parameter parameter) throws IOException { + if (this.parameters == null) { + return Optional.empty(); + } + JsonNode jsonNode = this.parameters.get(parameter.getKey()); + if (jsonNode == null) { + return Optional.empty(); + } + return Optional.ofNullable(parameter.apply(jsonNode, root())); + } + + /** + * The type of the ruleset. + */ + public static enum Type { /** - * all + * unknown */ - ALL, + UNKNOWN, /** - * errors + * creation */ - ERRORS, + CREATION, /** - * errors_and_warnings + * update */ - ERRORS_AND_WARNINGS, + UPDATE, /** - * none + * deletion */ - NONE - } + DELETION, - /** - * Boolean parameter for a ruleset. - */ - public static class BooleanParameter extends Parameter { /** - * Instantiates a new boolean parameter. - * - * @param key - * the key + * required_linear_history */ - public BooleanParameter(String key) { - super(key); - } + REQUIRED_LINEAR_HISTORY, - @Override - TypeReference getType() { - return new TypeReference() { - }; - } - } - /** - * Code scanning tool parameter. - */ - public static class CodeScanningTool { + /** + * required_deployments + */ + REQUIRED_DEPLOYMENTS, - private AlertsThreshold alertsThreshold; + /** + * required_signatures + */ + REQUIRED_SIGNATURES, - private SecurityAlertsThreshold securityAlertsThreshold; - private String tool; /** - * Create default CodeScanningTool instance + * pull_request */ - public CodeScanningTool() { - } + PULL_REQUEST, /** - * Gets the alerts threshold. - * - * @return the alerts threshold + * required_status_checks */ - public AlertsThreshold getAlertsThreshold() { - return this.alertsThreshold; - } + REQUIRED_STATUS_CHECKS, /** - * Gets the security alerts threshold. - * - * @return the security alerts threshold + * non_fast_forward */ - public SecurityAlertsThreshold getSecurityAlertsThreshold() { - return this.securityAlertsThreshold; - } + NON_FAST_FORWARD, /** - * Gets the tool. - * - * @return the tool + * commit_message_pattern */ - public String getTool() { - return this.tool; - } - } - /** - * Integer parameter for a ruleset. - */ - public static class IntegerParameter extends Parameter { + COMMIT_MESSAGE_PATTERN, + /** - * Instantiates a new integer parameter. - * - * @param key - * the key + * commit_author_email_pattern */ - public IntegerParameter(String key) { - super(key); - } + COMMIT_AUTHOR_EMAIL_PATTERN, - @Override - TypeReference getType() { - return new TypeReference() { - }; - } - } - /** - * List parameter for a ruleset. - * - * @param - * the type of the list - */ - public abstract static class ListParameter extends Parameter> { /** - * Instantiates a new list parameter. - * - * @param key - * the key + * committer_email_pattern */ - public ListParameter(String key) { - super(key); - } - } - /** - * Operator parameter. - */ - public static enum Operator { + COMMITTER_EMAIL_PATTERN, + /** - * contains + * branch_name_pattern */ - CONTAINS, + BRANCH_NAME_PATTERN, /** - * ends_with + * tag_name_pattern */ - ENDS_WITH, + TAG_NAME_PATTERN, /** - * regex + * workflows */ - REGEX, + WORKFLOWS, /** - * starts_with + * code_scanning */ - STARTS_WITH + CODE_SCANNING } /** - * Basic parameter for a ruleset. - * - * @param - * the type of the parameter + * The source of the ruleset type. */ - public abstract static class Parameter { - - private final String key; - + public enum RulesetSourceType { /** - * Instantiates a new parameter. - * - * @param key - * the key + * unknown */ - protected Parameter(String key) { - this.key = key; - } - - T apply(JsonNode jsonNode, GitHub root) throws IOException { - if (jsonNode == null) { - return null; - } - return GitHubClient.getMappingObjectReader(root).forType(this.getType()).readValue(jsonNode); - } + UNKNOWN, /** - * Gets the key. - * - * @return the key + * Repository */ - String getKey() { - return this.key; - } + REPOSITORY, /** - * Get the parameter type reference for type mapping. + * Organization */ - abstract TypeReference getType(); + ORGANIZATION } /** @@ -213,13 +202,18 @@ String getKey() { */ public interface Parameters { /** - * code_scanning_tools parameter + * update_allows_fetch_and_merge parameter */ - public static final ListParameter CODE_SCANNING_TOOLS = new ListParameter( - "code_scanning_tools") { + public static final BooleanParameter UPDATE_ALLOWS_FETCH_AND_MERGE = new BooleanParameter( + "update_allows_fetch_and_merge"); + /** + * required_deployment_environments parameter + */ + public static final ListParameter REQUIRED_DEPLOYMENT_ENVIRONMENTS = new ListParameter( + "required_deployment_environments") { @Override - TypeReference> getType() { - return new TypeReference>() { + TypeReference> getType() { + return new TypeReference>() { }; } }; @@ -229,43 +223,20 @@ TypeReference> getType() { public static final BooleanParameter DISMISS_STALE_REVIEWS_ON_PUSH = new BooleanParameter( "dismiss_stale_reviews_on_push"); /** - * name parameter - */ - public static final StringParameter NAME = new StringParameter("name"); - /** - * negate parameter - */ - public static final BooleanParameter NEGATE = new BooleanParameter("negate"); - /** - * operator parameter + * require_code_owner_review parameter */ - public static final Parameter OPERATOR = new Parameter("operator") { - @Override - TypeReference getType() { - return new TypeReference() { - }; - } - }; + public static final BooleanParameter REQUIRE_CODE_OWNER_REVIEW = new BooleanParameter( + "require_code_owner_review"); /** - * regex parameter + * require_last_push_approval parameter */ - public static final StringParameter REGEX = new StringParameter("regex"); + public static final BooleanParameter REQUIRE_LAST_PUSH_APPROVAL = new BooleanParameter( + "require_last_push_approval"); /** * required_approving_review_count parameter */ public static final IntegerParameter REQUIRED_APPROVING_REVIEW_COUNT = new IntegerParameter( "required_approving_review_count"); - /** - * required_deployment_environments parameter - */ - public static final ListParameter REQUIRED_DEPLOYMENT_ENVIRONMENTS = new ListParameter( - "required_deployment_environments") { - @Override - TypeReference> getType() { - return new TypeReference>() { - }; - } - }; /** * required_review_thread_resolution parameter */ @@ -283,25 +254,32 @@ TypeReference> getType() { } }; /** - * require_code_owner_review parameter + * strict_required_status_checks_policy parameter */ - public static final BooleanParameter REQUIRE_CODE_OWNER_REVIEW = new BooleanParameter( - "require_code_owner_review"); + public static final BooleanParameter STRICT_REQUIRED_STATUS_CHECKS_POLICY = new BooleanParameter( + "strict_required_status_checks_policy"); /** - * require_last_push_approval parameter + * name parameter */ - public static final BooleanParameter REQUIRE_LAST_PUSH_APPROVAL = new BooleanParameter( - "require_last_push_approval"); + public static final StringParameter NAME = new StringParameter("name"); /** - * strict_required_status_checks_policy parameter + * negate parameter */ - public static final BooleanParameter STRICT_REQUIRED_STATUS_CHECKS_POLICY = new BooleanParameter( - "strict_required_status_checks_policy"); + public static final BooleanParameter NEGATE = new BooleanParameter("negate"); /** - * update_allows_fetch_and_merge parameter + * operator parameter */ - public static final BooleanParameter UPDATE_ALLOWS_FETCH_AND_MERGE = new BooleanParameter( - "update_allows_fetch_and_merge"); + public static final Parameter OPERATOR = new Parameter("operator") { + @Override + TypeReference getType() { + return new TypeReference() { + }; + } + }; + /** + * regex parameter + */ + public static final StringParameter REGEX = new StringParameter("regex"); /** * workflows parameter */ @@ -313,56 +291,140 @@ TypeReference> getType() { }; } }; + /** + * code_scanning_tools parameter + */ + public static final ListParameter CODE_SCANNING_TOOLS = new ListParameter( + "code_scanning_tools") { + @Override + TypeReference> getType() { + return new TypeReference>() { + }; + } + }; } /** - * The source of the ruleset type. + * Basic parameter for a ruleset. + * + * @param + * the type of the parameter */ - public enum RulesetSourceType { + public abstract static class Parameter { + + private final String key; + /** - * Organization + * Get the parameter type reference for type mapping. */ - ORGANIZATION, + abstract TypeReference getType(); /** - * Repository + * Instantiates a new parameter. + * + * @param key + * the key */ - REPOSITORY, + protected Parameter(String key) { + this.key = key; + } /** - * unknown + * Gets the key. + * + * @return the key */ - UNKNOWN + String getKey() { + return this.key; + } + + T apply(JsonNode jsonNode, GitHub root) throws IOException { + if (jsonNode == null) { + return null; + } + return GitHubClient.getMappingObjectReader(root).forType(this.getType()).readValue(jsonNode); + } } /** - * Security alerts threshold parameter. + * String parameter for a ruleset. */ - public static enum SecurityAlertsThreshold { + public static class StringParameter extends Parameter { /** - * all + * Instantiates a new string parameter. + * + * @param key + * the key */ - ALL, + public StringParameter(String key) { + super(key); + } - /** - * critical - */ - CRITICAL, + @Override + TypeReference getType() { + return new TypeReference() { + }; + } + } + /** + * Boolean parameter for a ruleset. + */ + public static class BooleanParameter extends Parameter { /** - * high_or_higher + * Instantiates a new boolean parameter. + * + * @param key + * the key */ - HIGH_OR_HIGHER, + public BooleanParameter(String key) { + super(key); + } + + @Override + TypeReference getType() { + return new TypeReference() { + }; + } + } + /** + * Integer parameter for a ruleset. + */ + public static class IntegerParameter extends Parameter { /** - * medium_or_higher + * Instantiates a new integer parameter. + * + * @param key + * the key */ - MEDIUM_OR_HIGHER, + public IntegerParameter(String key) { + super(key); + } + @Override + TypeReference getType() { + return new TypeReference() { + }; + } + } + + /** + * List parameter for a ruleset. + * + * @param + * the type of the list + */ + public abstract static class ListParameter extends Parameter> { /** - * none + * Instantiates a new list parameter. + * + * @param key + * the key */ - NONE + public ListParameter(String key) { + super(key); + } } /** @@ -370,15 +432,15 @@ public static enum SecurityAlertsThreshold { */ public static class StatusCheckConfiguration { - private String context; - - private Integer integrationId; /** * Create default StatusCheckConfiguration instance */ public StatusCheckConfiguration() { } + private String context; + private Integer integrationId; + /** * Gets the context. * @@ -399,114 +461,28 @@ public Integer getIntegrationId() { } /** - * String parameter for a ruleset. - */ - public static class StringParameter extends Parameter { - /** - * Instantiates a new string parameter. - * - * @param key - * the key - */ - public StringParameter(String key) { - super(key); - } - - @Override - TypeReference getType() { - return new TypeReference() { - }; - } - } - - /** - * The type of the ruleset. + * Operator parameter. */ - public static enum Type { - /** - * branch_name_pattern - */ - BRANCH_NAME_PATTERN, - - /** - * code_scanning - */ - CODE_SCANNING, - - /** - * committer_email_pattern - */ - COMMITTER_EMAIL_PATTERN, - - /** - * commit_author_email_pattern - */ - COMMIT_AUTHOR_EMAIL_PATTERN, - - /** - * commit_message_pattern - */ - COMMIT_MESSAGE_PATTERN, - - /** - * creation - */ - CREATION, - - /** - * deletion - */ - DELETION, - - /** - * non_fast_forward - */ - NON_FAST_FORWARD, - - /** - * pull_request - */ - PULL_REQUEST, - - /** - * required_deployments - */ - REQUIRED_DEPLOYMENTS, - - /** - * required_linear_history - */ - REQUIRED_LINEAR_HISTORY, - - /** - * required_signatures - */ - REQUIRED_SIGNATURES, - - /** - * required_status_checks - */ - REQUIRED_STATUS_CHECKS, - + public static enum Operator { /** - * tag_name_pattern + * starts_with */ - TAG_NAME_PATTERN, + STARTS_WITH, /** - * unknown + * ends_with */ - UNKNOWN, + ENDS_WITH, /** - * update + * contains */ - UPDATE, + CONTAINS, /** - * workflows + * regex */ - WORKFLOWS + REGEX } /** @@ -514,17 +490,17 @@ public static enum Type { */ public static class WorkflowFileReference { - private String path; - - private String ref; - private long repositoryId; - private String sha; /** * Create default WorkflowFileReference instance */ public WorkflowFileReference() { } + private String path; + private String ref; + private long repositoryId; + private String sha; + /** * Gets the path. * @@ -562,77 +538,101 @@ public String getSha() { } } - private Map parameters; - - private long rulesetId; - - private String rulesetSource; + /** + * Code scanning tool parameter. + */ + public static class CodeScanningTool { - private String rulesetSourceType; + /** + * Create default CodeScanningTool instance + */ + public CodeScanningTool() { + } - private String type; + private AlertsThreshold alertsThreshold; + private SecurityAlertsThreshold securityAlertsThreshold; + private String tool; - /** - * Create default GHRepositoryRule instance - */ - public GHRepositoryRule() { - } + /** + * Gets the alerts threshold. + * + * @return the alerts threshold + */ + public AlertsThreshold getAlertsThreshold() { + return this.alertsThreshold; + } - /** - * Gets a parameter. ({@link GHRepositoryRule.Parameters Parameters} provides a list of available parameters.) - * - * @param parameter - * the parameter - * @param - * the type of the parameter - * @return the parameters - * @throws IOException - * if an I/O error occurs - */ - public Optional getParameter(Parameter parameter) throws IOException { - if (this.parameters == null) { - return Optional.empty(); + /** + * Gets the security alerts threshold. + * + * @return the security alerts threshold + */ + public SecurityAlertsThreshold getSecurityAlertsThreshold() { + return this.securityAlertsThreshold; } - JsonNode jsonNode = this.parameters.get(parameter.getKey()); - if (jsonNode == null) { - return Optional.empty(); + + /** + * Gets the tool. + * + * @return the tool + */ + public String getTool() { + return this.tool; } - return Optional.ofNullable(parameter.apply(jsonNode, root())); } /** - * Gets the ruleset id. - * - * @return the ruleset id + * Alerts threshold parameter. */ - public long getRulesetId() { - return this.rulesetId; - } + public static enum AlertsThreshold { + /** + * none + */ + NONE, - /** - * Gets the ruleset source. - * - * @return the ruleset source - */ - public String getRulesetSource() { - return this.rulesetSource; - } + /** + * errors + */ + ERRORS, - /** - * Gets the ruleset source type. - * - * @return the ruleset source type - */ - public RulesetSourceType getRulesetSourceType() { - return EnumUtils.getEnumOrDefault(RulesetSourceType.class, this.rulesetSourceType, RulesetSourceType.UNKNOWN); + /** + * errors_and_warnings + */ + ERRORS_AND_WARNINGS, + + /** + * all + */ + ALL } /** - * Gets the type. - * - * @return the type + * Security alerts threshold parameter. */ - public Type getType() { - return EnumUtils.getEnumOrDefault(Type.class, this.type, Type.UNKNOWN); + public static enum SecurityAlertsThreshold { + /** + * none + */ + NONE, + + /** + * critical + */ + CRITICAL, + + /** + * high_or_higher + */ + HIGH_OR_HIGHER, + + /** + * medium_or_higher + */ + MEDIUM_OR_HIGHER, + + /** + * all + */ + ALL } } diff --git a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java index 9e600ec927..c0e3220911 100644 --- a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java @@ -12,51 +12,53 @@ public class GHRepositorySearchBuilder extends GHSearchBuilder { /** - * The enum Sort. + * Instantiates a new GH repository search builder. + * + * @param root + * the root */ - public enum Sort { - - /** The forks. */ - FORKS, - /** The stars. */ - STARS, - /** The updated. */ - UPDATED + GHRepositorySearchBuilder(GitHub root) { + super(root, RepositorySearchResult.class); } - @SuppressFBWarnings( - value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, - justification = "JSON API") - private static class RepositorySearchResult extends SearchResult { - private GHRepository[] items; + /** + * {@inheritDoc} + */ + @Override + public GHRepositorySearchBuilder q(String term) { + super.q(term); + return this; + } - @Override - GHRepository[] getItems(GitHub root) { - for (GHRepository item : items) { - } - return items; - } + /** + * {@inheritDoc} + */ + @Override + GHRepositorySearchBuilder q(String qualifier, String value) { + super.q(qualifier, value); + return this; } /** - * Instantiates a new GH repository search builder. + * In gh repository search builder. * - * @param root - * the root + * @param v + * the v + * @return the gh repository search builder */ - GHRepositorySearchBuilder(GitHub root) { - super(root, RepositorySearchResult.class); + public GHRepositorySearchBuilder in(String v) { + return q("in:" + v); } /** - * Created gh repository search builder. + * Size gh repository search builder. * * @param v * the v * @return the gh repository search builder */ - public GHRepositorySearchBuilder created(String v) { - return q("created:" + v); + public GHRepositorySearchBuilder size(String v) { + return q("size:" + v); } /** @@ -88,68 +90,58 @@ public GHRepositorySearchBuilder fork(GHFork fork) { } /** - * In gh repository search builder. + * Search by repository visibility. * - * @param v - * the v + * @param visibility + * repository visibility * @return the gh repository search builder + * @throws GHException + * if {@link GHRepository.Visibility#UNKNOWN} is passed. UNKNOWN is a placeholder for unexpected values + * encountered when reading data. + * @see Search + * by repository visibility */ - public GHRepositorySearchBuilder in(String v) { - return q("in:" + v); - } + public GHRepositorySearchBuilder visibility(GHRepository.Visibility visibility) { + if (visibility == GHRepository.Visibility.UNKNOWN) { + throw new GHException( + "UNKNOWN is a placeholder for unexpected values encountered when reading data. It cannot be passed as a search parameter."); + } - /** - * Language gh repository search builder. - * - * @param v - * the v - * @return the gh repository search builder - */ - public GHRepositorySearchBuilder language(String v) { - return q("language:" + v); + return q("is:" + visibility); } /** - * Order gh repository search builder. + * Created gh repository search builder. * * @param v * the v * @return the gh repository search builder */ - public GHRepositorySearchBuilder order(GHDirection v) { - req.with("order", v); - return this; + public GHRepositorySearchBuilder created(String v) { + return q("created:" + v); } /** - * Org gh repository search builder. + * Pushed gh repository search builder. * * @param v * the v * @return the gh repository search builder */ - public GHRepositorySearchBuilder org(String v) { - return q("org:" + v); + public GHRepositorySearchBuilder pushed(String v) { + return q("pushed:" + v); } /** - * Pushed gh repository search builder. + * User gh repository search builder. * * @param v * the v * @return the gh repository search builder */ - public GHRepositorySearchBuilder pushed(String v) { - return q("pushed:" + v); - } - - /** - * {@inheritDoc} - */ - @Override - public GHRepositorySearchBuilder q(String term) { - super.q(term); - return this; + public GHRepositorySearchBuilder user(String v) { + return q("user:" + v); } /** @@ -164,26 +156,14 @@ public GHRepositorySearchBuilder repo(String v) { } /** - * Size gh repository search builder. + * Language gh repository search builder. * * @param v * the v * @return the gh repository search builder */ - public GHRepositorySearchBuilder size(String v) { - return q("size:" + v); - } - - /** - * Sort gh repository search builder. - * - * @param sort - * the sort - * @return the gh repository search builder - */ - public GHRepositorySearchBuilder sort(Sort sort) { - req.with("sort", sort); - return this; + public GHRepositorySearchBuilder language(String v) { + return q("language:" + v); } /** @@ -209,36 +189,65 @@ public GHRepositorySearchBuilder topic(String v) { } /** - * User gh repository search builder. + * Org gh repository search builder. * * @param v * the v * @return the gh repository search builder */ - public GHRepositorySearchBuilder user(String v) { - return q("user:" + v); + public GHRepositorySearchBuilder org(String v) { + return q("org:" + v); } /** - * Search by repository visibility. + * Order gh repository search builder. * - * @param visibility - * repository visibility + * @param v + * the v * @return the gh repository search builder - * @throws GHException - * if {@link GHRepository.Visibility#UNKNOWN} is passed. UNKNOWN is a placeholder for unexpected values - * encountered when reading data. - * @see Search - * by repository visibility */ - public GHRepositorySearchBuilder visibility(GHRepository.Visibility visibility) { - if (visibility == GHRepository.Visibility.UNKNOWN) { - throw new GHException( - "UNKNOWN is a placeholder for unexpected values encountered when reading data. It cannot be passed as a search parameter."); - } + public GHRepositorySearchBuilder order(GHDirection v) { + req.with("order", v); + return this; + } - return q("is:" + visibility); + /** + * Sort gh repository search builder. + * + * @param sort + * the sort + * @return the gh repository search builder + */ + public GHRepositorySearchBuilder sort(Sort sort) { + req.with("sort", sort); + return this; + } + + /** + * The enum Sort. + */ + public enum Sort { + + /** The stars. */ + STARS, + /** The forks. */ + FORKS, + /** The updated. */ + UPDATED + } + + @SuppressFBWarnings( + value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, + justification = "JSON API") + private static class RepositorySearchResult extends SearchResult { + private GHRepository[] items; + + @Override + GHRepository[] getItems(GitHub root) { + for (GHRepository item : items) { + } + return items; + } } /** @@ -250,13 +259,4 @@ public GHRepositorySearchBuilder visibility(GHRepository.Visibility visibility) protected String getApiUrl() { return "/search/repositories"; } - - /** - * {@inheritDoc} - */ - @Override - GHRepositorySearchBuilder q(String qualifier, String value) { - super.q(qualifier, value); - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHRepositorySelection.java b/src/main/java/org/kohsuke/github/GHRepositorySelection.java index ff11023483..2833eeabcd 100644 --- a/src/main/java/org/kohsuke/github/GHRepositorySelection.java +++ b/src/main/java/org/kohsuke/github/GHRepositorySelection.java @@ -11,10 +11,10 @@ */ public enum GHRepositorySelection { - /** The all. */ - ALL, /** The selected. */ - SELECTED; + SELECTED, + /** The all. */ + ALL; /** * Returns GitHub's internal representation of this event. diff --git a/src/main/java/org/kohsuke/github/GHRepositoryStatistics.java b/src/main/java/org/kohsuke/github/GHRepositoryStatistics.java index ece1e9d87d..4de7fbad5f 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryStatistics.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryStatistics.java @@ -18,116 +18,156 @@ */ public class GHRepositoryStatistics extends GitHubInteractiveObject { + private final GHRepository repo; + + private static final int MAX_WAIT_ITERATIONS = 3; + private static final int WAIT_SLEEP_INTERVAL = 5000; + /** - * The type CodeFrequency. + * Instantiates a new Gh repository statistics. + * + * @param repo + * the repo */ - public static class CodeFrequency { - - private final int additions; - private final int deletions; - private final int week; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Acceptable risk") + public GHRepositoryStatistics(GHRepository repo) { + super(repo.root()); + this.repo = repo; + } - @JsonCreator(mode = JsonCreator.Mode.DELEGATING) - private CodeFrequency(List item) { - week = item.get(0); - additions = item.get(1); - deletions = item.get(2); - } + /** + * Get contributors list with additions, deletions, and commit count. See + * https://developer.github.com/v3/repos/statistics/#get-contributors-list-with-additions-deletions-and-commit-counts + * + * @return the contributor stats + * @throws IOException + * the io exception + * @throws InterruptedException + * the interrupted exception + */ + public PagedIterable getContributorStats() throws IOException, InterruptedException { + return getContributorStats(true); + } - /** - * Gets additions. - * - * @return The number of additions for the week. - */ - public long getAdditions() { - return additions; - } + /** + * Gets contributor stats. + * + * @param waitTillReady + * Whether to sleep the thread if necessary until the statistics are ready. This is true by default. + * @return the contributor stats + * @throws IOException + * the io exception + * @throws InterruptedException + * the interrupted exception + */ + @BetaApi + @SuppressWarnings("SleepWhileInLoop") + @SuppressFBWarnings(value = { "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" }, justification = "JSON API") + public PagedIterable getContributorStats(boolean waitTillReady) + throws IOException, InterruptedException { + PagedIterable stats = getContributorStatsImpl(); - /** - * Gets deletions. - * - * @return The number of deletions for the week. NOTE: This will be a NEGATIVE number. - */ - public long getDeletions() { - // TODO: Perhaps return Math.abs(deletions), - // since most developers may not expect a negative number. - return deletions; + if (stats == null && waitTillReady) { + for (int i = 0; i < MAX_WAIT_ITERATIONS; i += 1) { + // Wait a few seconds and try again. + Thread.sleep(WAIT_SLEEP_INTERVAL); + stats = getContributorStatsImpl(); + if (stats != null) { + break; + } + } } - /** - * Gets week timestamp. - * - * @return The start of the week as a UNIX timestamp. - */ - public int getWeekTimestamp() { - return week; - } + return stats; + } - /** - * To string. - * - * @return the string - */ - @Override - public String toString() { - return "Week starting " + getWeekTimestamp() + " has " + getAdditions() + " additions and " - + Math.abs(getDeletions()) + " deletions"; - } + /** + * This gets the actual statistics from the server. Returns null if they are still being cached. + */ + private PagedIterable getContributorStatsImpl() throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("contributors")) + .toIterable(ContributorStats[].class, null); } /** - * The type CommitActivity. + * The type ContributorStats. */ @SuppressFBWarnings( - value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, + value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", + "URF_UNREAD_FIELD" }, justification = "JSON API") - public static class CommitActivity extends GHObject { - - private List days; + public static class ContributorStats extends GHObject { - private int total; - private long week; /** - * Create default CommitActivity instance + * Create default ContributorStats instance */ - public CommitActivity() { + public ContributorStats() { } + private GHUser author; + private int total; + private List weeks; + /** - * Gets days. + * Gets author. * - * @return The number of commits for each day of the week. 0 = Sunday, 1 = Monday, etc. + * @return The author described by these statistics. */ - public List getDays() { - return Collections.unmodifiableList(days); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHUser getAuthor() { + return author; } /** * Gets total. * - * @return The total number of commits for the week. + * @return The total number of commits authored by the contributor. */ public int getTotal() { return total; } /** - * Gets week. + * Convenience method to look up week with particular timestamp. * - * @return The start of the week as a UNIX timestamp. + * @param timestamp + * The timestamp to look for. + * @return The week starting with the given timestamp. Throws an exception if it is not found. + * @throws NoSuchElementException + * the no such element exception */ - public long getWeek() { - return week; + public Week getWeek(long timestamp) throws NoSuchElementException { + // maybe store the weeks in a map to make this more efficient? + for (Week week : weeks) { + if (week.getWeekTimestamp() == timestamp) { + return week; + } + } + + // this is safer than returning null + throw new NoSuchElementException(); + } + + /** + * Gets weeks. + * + * @return The total number of commits authored by the contributor. + */ + public List getWeeks() { + return Collections.unmodifiableList(weeks); + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + return author.getLogin() + " made " + String.valueOf(total) + " contributions over " + + String.valueOf(weeks.size()) + " weeks"; } - } - /** - * The type ContributorStats. - */ - @SuppressFBWarnings( - value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", - "URF_UNREAD_FIELD" }, - justification = "JSON API") - public static class ContributorStats extends GHObject { /** * The type Week. @@ -138,33 +178,33 @@ public static class ContributorStats extends GHObject { justification = "JSON API") public static class Week { - private int a; - - private int c; - private int d; - private long w; /** * Create default Week instance */ public Week() { } + private long w; + private int a; + private int d; + private int c; + /** - * Gets number of additions. + * Gets week timestamp. * - * @return The number of additions for the week. + * @return Start of the week, as a UNIX timestamp. */ - public int getNumberOfAdditions() { - return a; + public long getWeekTimestamp() { + return w; } /** - * Gets number of commits. + * Gets number of additions. * - * @return The number of commits for the week. + * @return The number of additions for the week. */ - public int getNumberOfCommits() { - return c; + public int getNumberOfAdditions() { + return a; } /** @@ -177,12 +217,12 @@ public int getNumberOfDeletions() { } /** - * Gets week timestamp. + * Gets number of commits. * - * @return Start of the week, as a UNIX timestamp. + * @return The number of commits for the week. */ - public long getWeekTimestamp() { - return w; + public int getNumberOfCommits() { + return c; } /** @@ -195,64 +235,134 @@ public String toString() { return String.format("Week starting %d - Additions: %d, Deletions: %d, Commits: %d", w, a, d, c); } } + } - private GHUser author; - private int total; - private List weeks; + /** + * Get the last year of commit activity data. See + * https://developer.github.com/v3/repos/statistics/#get-the-last-year-of-commit-activity-data + * + * @return the commit activity + * @throws IOException + * the io exception + */ + public PagedIterable getCommitActivity() throws IOException { + return root().createRequest() + .withUrlPath(getApiTailUrl("commit_activity")) + .toIterable(CommitActivity[].class, null); + } + + /** + * The type CommitActivity. + */ + @SuppressFBWarnings( + value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, + justification = "JSON API") + public static class CommitActivity extends GHObject { /** - * Create default ContributorStats instance + * Create default CommitActivity instance */ - public ContributorStats() { + public CommitActivity() { } + private List days; + private int total; + private long week; + /** - * Gets author. + * Gets days. * - * @return The author described by these statistics. + * @return The number of commits for each day of the week. 0 = Sunday, 1 = Monday, etc. */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getAuthor() { - return author; + public List getDays() { + return Collections.unmodifiableList(days); } /** * Gets total. * - * @return The total number of commits authored by the contributor. + * @return The total number of commits for the week. */ public int getTotal() { return total; } /** - * Convenience method to look up week with particular timestamp. + * Gets week. * - * @param timestamp - * The timestamp to look for. - * @return The week starting with the given timestamp. Throws an exception if it is not found. - * @throws NoSuchElementException - * the no such element exception + * @return The start of the week as a UNIX timestamp. */ - public Week getWeek(long timestamp) throws NoSuchElementException { - // maybe store the weeks in a map to make this more efficient? - for (Week week : weeks) { - if (week.getWeekTimestamp() == timestamp) { - return week; - } - } + public long getWeek() { + return week; + } + } - // this is safer than returning null - throw new NoSuchElementException(); + /** + * Get the number of additions and deletions per week. See + * https://developer.github.com/v3/repos/statistics/#get-the-number-of-additions-and-deletions-per-week + * + * @return the code frequency + * @throws IOException + * the io exception + */ + public List getCodeFrequency() throws IOException { + try { + CodeFrequency[] list = root().createRequest() + .withUrlPath(getApiTailUrl("code_frequency")) + .fetch(CodeFrequency[].class); + + return Arrays.asList(list); + } catch (MismatchedInputException e) { + // This sometimes happens when retrieving code frequency statistics + // for a repository for the first time. It is probably still being + // generated, so return null. + return null; + } + } + + /** + * The type CodeFrequency. + */ + public static class CodeFrequency { + + private final int week; + private final int additions; + private final int deletions; + + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + private CodeFrequency(List item) { + week = item.get(0); + additions = item.get(1); + deletions = item.get(2); } /** - * Gets weeks. + * Gets week timestamp. * - * @return The total number of commits authored by the contributor. + * @return The start of the week as a UNIX timestamp. */ - public List getWeeks() { - return Collections.unmodifiableList(weeks); + public int getWeekTimestamp() { + return week; + } + + /** + * Gets additions. + * + * @return The number of additions for the week. + */ + public long getAdditions() { + return additions; + } + + /** + * Gets deletions. + * + * @return The number of deletions for the week. NOTE: This will be a NEGATIVE number. + */ + public long getDeletions() { + // TODO: Perhaps return Math.abs(deletions), + // since most developers may not expect a negative number. + return deletions; } /** @@ -262,25 +372,37 @@ public List getWeeks() { */ @Override public String toString() { - return author.getLogin() + " made " + String.valueOf(total) + " contributions over " - + String.valueOf(weeks.size()) + " weeks"; + return "Week starting " + getWeekTimestamp() + " has " + getAdditions() + " additions and " + + Math.abs(getDeletions()) + " deletions"; } } + /** + * Get the weekly commit count for the repository owner and everyone else. See + * https://developer.github.com/v3/repos/statistics/#get-the-weekly-commit-count-for-the-repository-owner-and-everyone-else + * + * @return the participation + * @throws IOException + * the io exception + */ + public Participation getParticipation() throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("participation")).fetch(Participation.class); + } + /** * The type Participation. */ public static class Participation extends GHObject { - private List all; - - private List owner; /** * Create default Participation instance */ public Participation() { } + private List all; + private List owner; + /** * Gets all commits. * @@ -300,6 +422,21 @@ public List getOwnerCommits() { } } + /** + * Get the number of commits per hour in each day. See + * https://developer.github.com/v3/repos/statistics/#get-the-number-of-commits-per-hour-in-each-day + * + * @return the punch card + * @throws IOException + * the io exception + */ + public List getPunchCard() throws IOException { + PunchCardItem[] list = root().createRequest() + .withUrlPath(getApiTailUrl("punch_card")) + .fetch(PunchCardItem[].class); + return Arrays.asList(list); + } + /** * The type PunchCardItem. */ @@ -353,136 +490,6 @@ public String toString() { } } - private static final int MAX_WAIT_ITERATIONS = 3; - - private static final int WAIT_SLEEP_INTERVAL = 5000; - - private final GHRepository repo; - - /** - * Instantiates a new Gh repository statistics. - * - * @param repo - * the repo - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Acceptable risk") - public GHRepositoryStatistics(GHRepository repo) { - super(repo.root()); - this.repo = repo; - } - - /** - * Get the number of additions and deletions per week. See - * https://developer.github.com/v3/repos/statistics/#get-the-number-of-additions-and-deletions-per-week - * - * @return the code frequency - * @throws IOException - * the io exception - */ - public List getCodeFrequency() throws IOException { - try { - CodeFrequency[] list = root().createRequest() - .withUrlPath(getApiTailUrl("code_frequency")) - .fetch(CodeFrequency[].class); - - return Arrays.asList(list); - } catch (MismatchedInputException e) { - // This sometimes happens when retrieving code frequency statistics - // for a repository for the first time. It is probably still being - // generated, so return null. - return null; - } - } - - /** - * Get the last year of commit activity data. See - * https://developer.github.com/v3/repos/statistics/#get-the-last-year-of-commit-activity-data - * - * @return the commit activity - */ - public PagedIterable getCommitActivity() { - return root().createRequest() - .withUrlPath(getApiTailUrl("commit_activity")) - .toIterable(CommitActivity[].class, null); - } - - /** - * Get contributors list with additions, deletions, and commit count. See - * https://developer.github.com/v3/repos/statistics/#get-contributors-list-with-additions-deletions-and-commit-counts - * - * @return the contributor stats - * @throws InterruptedException - * the interrupted exception - */ - public PagedIterable getContributorStats() throws InterruptedException { - return getContributorStats(true); - } - - /** - * Gets contributor stats. - * - * @param waitTillReady - * Whether to sleep the thread if necessary until the statistics are ready. This is true by default. - * @return the contributor stats - * @throws InterruptedException - * the interrupted exception - */ - @BetaApi - @SuppressWarnings("SleepWhileInLoop") - @SuppressFBWarnings(value = { "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" }, justification = "JSON API") - public PagedIterable getContributorStats(boolean waitTillReady) throws InterruptedException { - PagedIterable stats = getContributorStatsImpl(); - - if (stats == null && waitTillReady) { - for (int i = 0; i < MAX_WAIT_ITERATIONS; i += 1) { - // Wait a few seconds and try again. - Thread.sleep(WAIT_SLEEP_INTERVAL); - stats = getContributorStatsImpl(); - if (stats != null) { - break; - } - } - } - - return stats; - } - - /** - * Get the weekly commit count for the repository owner and everyone else. See - * https://developer.github.com/v3/repos/statistics/#get-the-weekly-commit-count-for-the-repository-owner-and-everyone-else - * - * @return the participation - * @throws IOException - * the io exception - */ - public Participation getParticipation() throws IOException { - return root().createRequest().withUrlPath(getApiTailUrl("participation")).fetch(Participation.class); - } - - /** - * Get the number of commits per hour in each day. See - * https://developer.github.com/v3/repos/statistics/#get-the-number-of-commits-per-hour-in-each-day - * - * @return the punch card - * @throws IOException - * the io exception - */ - public List getPunchCard() throws IOException { - PunchCardItem[] list = root().createRequest() - .withUrlPath(getApiTailUrl("punch_card")) - .fetch(PunchCardItem[].class); - return Arrays.asList(list); - } - - /** - * This gets the actual statistics from the server. Returns null if they are still being cached. - */ - private PagedIterable getContributorStatsImpl() { - return root().createRequest() - .withUrlPath(getApiTailUrl("contributors")) - .toIterable(ContributorStats[].class, null); - } - /** * Gets the api tail url. * diff --git a/src/main/java/org/kohsuke/github/GHRepositoryTraffic.java b/src/main/java/org/kohsuke/github/GHRepositoryTraffic.java index 924bb3e1ab..49738fceff 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryTraffic.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryTraffic.java @@ -1,8 +1,5 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; - -import java.time.Instant; import java.util.Date; import java.util.List; @@ -10,67 +7,8 @@ /** * The type GHRepositoryTraffic. */ -public abstract class GHRepositoryTraffic extends GitHubBridgeAdapterObject implements TrafficInfo { - /** - * The type DailyInfo. - */ - public static abstract class DailyInfo implements TrafficInfo { - private int count; - private String timestamp; - private int uniques; - - /** - * Instantiates a new daily info. - */ - DailyInfo() { - } - - /** - * Instantiates a new daily info. - * - * @param timestamp - * the timestamp - * @param count - * the count - * @param uniques - * the uniques - */ - DailyInfo(String timestamp, Integer count, Integer uniques) { - this.timestamp = timestamp; - this.count = count; - this.uniques = uniques; - } - - /** - * Gets the count. - * - * @return the count - */ - public int getCount() { - return count; - } - - /** - * Gets timestamp. - * - * @return the timestamp - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getTimestamp() { - return GitHubClient.parseInstant(timestamp); - } - - /** - * Gets the uniques. - * - * @return the uniques - */ - public int getUniques() { - return uniques; - } - } +public abstract class GHRepositoryTraffic implements TrafficInfo { private int count; - private int uniques; /** @@ -101,6 +39,15 @@ public int getCount() { return count; } + /** + * Gets the uniques. + * + * @return the uniques + */ + public int getUniques() { + return uniques; + } + /** * Gets daily info. * @@ -109,11 +56,60 @@ public int getCount() { public abstract List getDailyInfo(); /** - * Gets the uniques. - * - * @return the uniques + * The type DailyInfo. */ - public int getUniques() { - return uniques; + public static abstract class DailyInfo implements TrafficInfo { + private String timestamp; + private int count; + private int uniques; + + /** + * Gets timestamp. + * + * @return the timestamp + */ + public Date getTimestamp() { + return GitHubClient.parseDate(timestamp); + } + + /** + * Gets the count. + * + * @return the count + */ + public int getCount() { + return count; + } + + /** + * Gets the uniques. + * + * @return the uniques + */ + public int getUniques() { + return uniques; + } + + /** + * Instantiates a new daily info. + */ + DailyInfo() { + } + + /** + * Instantiates a new daily info. + * + * @param timestamp + * the timestamp + * @param count + * the count + * @param uniques + * the uniques + */ + DailyInfo(String timestamp, Integer count, Integer uniques) { + this.timestamp = timestamp; + this.count = count; + this.uniques = uniques; + } } } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryVariable.java b/src/main/java/org/kohsuke/github/GHRepositoryVariable.java index 22b1556578..6a45c6cf98 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryVariable.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryVariable.java @@ -13,46 +13,78 @@ public class GHRepositoryVariable extends GitHubInteractiveObject { /** - * A {@link GHRepositoryVariableBuilder} that creates a new {@link GHRepositoryVariable} - *

- * Consumer must call {@link #done()} to create the new instance. + * Create default GHRepositoryVariable instance */ - @BetaApi - public static class Creator extends GHRepositoryVariableBuilder { - private Creator(@Nonnull GHRepository repository) { - super(GHRepositoryVariable.Creator.class, repository.root(), null); - requester.method("POST").withUrlPath(repository.getApiTailUrl(VARIABLE_NAMESPACE)); - } + public GHRepositoryVariable() { } + private static final String SLASH = "/"; + + private static final String VARIABLE_NAMESPACE = "actions/variables"; + + private String name; + private String value; + + private String url; + private String createdAt; + private String updatedAt; + /** - * A {@link GHRepositoryVariableBuilder} that updates a single property per request - *

- * {@link #done()} is called automatically after the property is set. + * Gets url. + * + * @return the url */ - @BetaApi - public static class Setter extends GHRepositoryVariableBuilder { - private Setter(@Nonnull GHRepositoryVariable base) { - super(GHRepositoryVariable.class, base.getApiRoot(), base); - requester.method("PATCH").withUrlPath(base.getUrl().concat(SLASH).concat(base.getName())); - } + @Nonnull + public String getUrl() { + return url; } - private static final String SLASH = "/"; + /** + * Gets name. + * + * @return the name + */ + public String getName() { + return name; + } - private static final String VARIABLE_NAMESPACE = "actions/variables"; /** - * Begins the creation of a new instance. - *

- * Consumer must call {@link GHRepositoryVariable.Creator#done()} to commit changes. + * Sets name. * - * @param repository - * the repository in which the variable will be created. - * @return a {@link GHRepositoryVariable.Creator} + * @param name + * the name */ - @BetaApi - static GHRepositoryVariable.Creator create(GHRepository repository) { - return new GHRepositoryVariable.Creator(repository); + public void setName(String name) { + this.name = name; + } + + /** + * Gets value. + * + * @return the value + */ + public String getValue() { + return value; + } + + /** + * Sets value. + * + * @param value + * the value + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Gets the api root. + * + * @return the api root + */ + @Nonnull + GitHub getApiRoot() { + return Objects.requireNonNull(root()); } /** @@ -74,19 +106,21 @@ static GHRepositoryVariable read(@Nonnull GHRepository repository, @Nonnull Stri variable.url = repository.getApiTailUrl("actions/variables"); return variable; } - private String createdAt; - private String name; - - private String updatedAt; - - private String url; - - private String value; /** - * Create default GHRepositoryVariable instance + * Begins the creation of a new instance. + *

+ * Consumer must call {@link GHRepositoryVariable.Creator#done()} to commit changes. + * + * @param repository + * the repository in which the variable will be created. + * @return a {@link GHRepositoryVariable.Creator} + * @throws IOException + * the io exception */ - public GHRepositoryVariable() { + @BetaApi + static GHRepositoryVariable.Creator create(GHRepository repository) throws IOException { + return new GHRepositoryVariable.Creator(repository); } /** @@ -99,34 +133,6 @@ public void delete() throws IOException { root().createRequest().method("DELETE").withUrlPath(getUrl().concat(SLASH).concat(name)).send(); } - /** - * Gets name. - * - * @return the name - */ - public String getName() { - return name; - } - - /** - * Gets url. - * - * @return the url - */ - @Nonnull - public String getUrl() { - return url; - } - - /** - * Gets value. - * - * @return the value - */ - public String getValue() { - return value; - } - /** * Begins a single property update. * @@ -138,33 +144,29 @@ public GHRepositoryVariable.Setter set() { } /** - * Sets name. - * - * @param name - * the name - */ - public void setName(String name) { - this.name = name; - } - - /** - * Sets value. - * - * @param value - * the value + * A {@link GHRepositoryVariableBuilder} that updates a single property per request + *

+ * {@link #done()} is called automatically after the property is set. */ - public void setValue(String value) { - this.value = value; + @BetaApi + public static class Setter extends GHRepositoryVariableBuilder { + private Setter(@Nonnull GHRepositoryVariable base) { + super(GHRepositoryVariable.class, base.getApiRoot(), base); + requester.method("PATCH").withUrlPath(base.getUrl().concat(SLASH).concat(base.getName())); + } } /** - * Gets the api root. - * - * @return the api root + * A {@link GHRepositoryVariableBuilder} that creates a new {@link GHRepositoryVariable} + *

+ * Consumer must call {@link #done()} to create the new instance. */ - @Nonnull - GitHub getApiRoot() { - return Objects.requireNonNull(root()); + @BetaApi + public static class Creator extends GHRepositoryVariableBuilder { + private Creator(@Nonnull GHRepository repository) { + super(GHRepositoryVariable.Creator.class, repository.root(), null); + requester.method("POST").withUrlPath(repository.getApiTailUrl(VARIABLE_NAMESPACE)); + } } } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryVariableBuilder.java b/src/main/java/org/kohsuke/github/GHRepositoryVariableBuilder.java index 0bbd874288..62af8140d8 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryVariableBuilder.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryVariableBuilder.java @@ -17,7 +17,7 @@ public class GHRepositoryVariableBuilder extends AbstractBuilder views; /** @@ -59,6 +33,15 @@ public static class DailyInfo extends GHRepositoryTraffic.DailyInfo { this.views = views; } + /** + * Gets views. + * + * @return the views + */ + public List getViews() { + return Collections.unmodifiableList(views); + } + /** * Gets the daily info. * @@ -69,11 +52,28 @@ public List getDailyInfo() { } /** - * Gets views. - * - * @return the views + * The type DailyInfo. */ - public List getViews() { - return Collections.unmodifiableList(views); + public static class DailyInfo extends GHRepositoryTraffic.DailyInfo { + + /** + * Instantiates a new daily info. + */ + DailyInfo() { + } + + /** + * Instantiates a new daily info. + * + * @param timestamp + * the timestamp + * @param count + * the count + * @param uniques + * the uniques + */ + DailyInfo(String timestamp, int count, int uniques) { + super(timestamp, count, uniques); + } } } diff --git a/src/main/java/org/kohsuke/github/GHRequestedAction.java b/src/main/java/org/kohsuke/github/GHRequestedAction.java index de4c701ebe..cec1349731 100644 --- a/src/main/java/org/kohsuke/github/GHRequestedAction.java +++ b/src/main/java/org/kohsuke/github/GHRequestedAction.java @@ -10,33 +10,36 @@ justification = "JSON API") public class GHRequestedAction extends GHObject { - private String description; - - private String identifier; - private String label; - private GHRepository owner; /** * Create default GHRequestedAction instance */ public GHRequestedAction() { } + private GHRepository owner; + private String identifier; + private String label; + private String description; + /** - * Gets the identifier. + * Wrap. * - * @return the identifier + * @param owner + * the owner + * @return the GH requested action */ - public String getIdentifier() { - return identifier; + GHRequestedAction wrap(GHRepository owner) { + this.owner = owner; + return this; } /** - * Gets the description. + * Gets the identifier. * - * @return the description + * @return the identifier */ - String getDescription() { - return description; + public String getIdentifier() { + return identifier; } /** @@ -49,15 +52,12 @@ String getLabel() { } /** - * Wrap. + * Gets the description. * - * @param owner - * the owner - * @return the GH requested action + * @return the description */ - GHRequestedAction wrap(GHRepository owner) { - this.owner = owner; - return this; + String getDescription() { + return description; } } diff --git a/src/main/java/org/kohsuke/github/GHSearchBuilder.java b/src/main/java/org/kohsuke/github/GHSearchBuilder.java index ea6317426c..d7a25353ee 100644 --- a/src/main/java/org/kohsuke/github/GHSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHSearchBuilder.java @@ -18,14 +18,14 @@ */ public abstract class GHSearchBuilder extends GHQueryBuilder { + /** The terms. */ + protected final List terms = new ArrayList(); + /** * Data transfer object that receives the result of search. */ private final Class> receiverType; - /** The terms. */ - protected final List terms = new ArrayList(); - /** * Instantiates a new GH search builder. * @@ -41,18 +41,6 @@ public abstract class GHSearchBuilder extends GHQueryBuilder { req.rateLimit(RateLimitTarget.SEARCH); } - /** - * Performs the search. - * - * @return the paged search iterable - */ - @Override - public PagedSearchIterable list() { - - req.set("q", StringUtils.join(terms, " ")); - return new PagedSearchIterable<>(root(), req.build(), receiverType); - } - /** * Search terms. * @@ -65,13 +53,6 @@ public GHQueryBuilder q(String term) { return this; } - /** - * Gets api url. - * - * @return the api url - */ - protected abstract String getApiUrl(); - /** * Add a search term with qualifier. * @@ -95,4 +76,23 @@ GHQueryBuilder q(@Nonnull final String qualifier, @CheckForNull final String } return this; } + + /** + * Performs the search. + * + * @return the paged search iterable + */ + @Override + public PagedSearchIterable list() { + + req.set("q", StringUtils.join(terms, " ")); + return new PagedSearchIterable<>(root(), req.build(), receiverType); + } + + /** + * Gets api url. + * + * @return the api url + */ + protected abstract String getApiUrl(); } diff --git a/src/main/java/org/kohsuke/github/GHStargazer.java b/src/main/java/org/kohsuke/github/GHStargazer.java index 7d14ba8efb..1b9862295a 100644 --- a/src/main/java/org/kohsuke/github/GHStargazer.java +++ b/src/main/java/org/kohsuke/github/GHStargazer.java @@ -1,9 +1,7 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -13,18 +11,18 @@ * @author noctarius */ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") -public class GHStargazer extends GitHubBridgeAdapterObject { +public class GHStargazer { - private GHRepository repository; - - private String starredAt; - private GHUser user; /** * Create default GHStargazer instance */ public GHStargazer() { } + private GHRepository repository; + private String starred_at; + private GHUser user; + /** * Gets the repository that is stargazed. * @@ -37,13 +35,12 @@ public GHRepository getRepository() { /** * Gets the date when the repository was starred, however old stars before August 2012, will all show the date the - * API was changed to support starredAt. + * API was changed to support starred_at. * * @return the date the stargazer was added */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getStarredAt() { - return GitHubClient.parseInstant(starredAt); + public Date getStarredAt() { + return GitHubClient.parseDate(starred_at); } /** diff --git a/src/main/java/org/kohsuke/github/GHSubscription.java b/src/main/java/org/kohsuke/github/GHSubscription.java index ad26bfb612..1066d51b7b 100644 --- a/src/main/java/org/kohsuke/github/GHSubscription.java +++ b/src/main/java/org/kohsuke/github/GHSubscription.java @@ -1,10 +1,8 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -17,72 +15,60 @@ */ public class GHSubscription extends GitHubInteractiveObject { - private String createdAt, url, repositoryUrl, reason; - - private GHRepository repo; - private boolean subscribed, ignored; - /** * Create default GHSubscription instance */ public GHSubscription() { } - /** - * Removes this subscription. - * - * @throws IOException - * the io exception - */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(repo.getApiTailUrl("subscription")).send(); - } + private String created_at, url, repository_url, reason; + private boolean subscribed, ignored; + + private GHRepository repo; /** * Gets created at. * * @return the created at */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCreatedAt() { - return GitHubClient.parseInstant(createdAt); + public Date getCreatedAt() { + return GitHubClient.parseDate(created_at); } /** - * Gets reason. + * Gets url. * - * @return the reason + * @return the url */ - public String getReason() { - return reason; + public String getUrl() { + return url; } /** - * Gets repository. + * Gets repository url. * - * @return the repository + * @return the repository url */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getRepository() { - return repo; + public String getRepositoryUrl() { + return repository_url; } /** - * Gets repository url. + * Gets reason. * - * @return the repository url + * @return the reason */ - public String getRepositoryUrl() { - return repositoryUrl; + public String getReason() { + return reason; } /** - * Gets url. + * Is subscribed boolean. * - * @return the url + * @return the boolean */ - public String getUrl() { - return url; + public boolean isSubscribed() { + return subscribed; } /** @@ -95,12 +81,23 @@ public boolean isIgnored() { } /** - * Is subscribed boolean. + * Gets repository. * - * @return the boolean + * @return the repository */ - public boolean isSubscribed() { - return subscribed; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getRepository() { + return repo; + } + + /** + * Removes this subscription. + * + * @throws IOException + * the io exception + */ + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(repo.getApiTailUrl("subscription")).send(); } /** diff --git a/src/main/java/org/kohsuke/github/GHTag.java b/src/main/java/org/kohsuke/github/GHTag.java index 0f44d1a427..1487256d2c 100644 --- a/src/main/java/org/kohsuke/github/GHTag.java +++ b/src/main/java/org/kohsuke/github/GHTag.java @@ -12,25 +12,39 @@ justification = "JSON API") public class GHTag extends GitHubInteractiveObject { - private GHCommit commit; + /** + * Create default GHTag instance + */ + public GHTag() { + } + + private GHRepository owner; private String name; + private GHCommit commit; - private GHRepository owner; /** - * Create default GHTag instance + * Wrap. + * + * @param owner + * the owner + * @return the GH tag */ - public GHTag() { + GHTag wrap(GHRepository owner) { + this.owner = owner; + if (commit != null) + commit.wrapUp(owner); + return this; } /** - * Gets commit. + * Gets owner. * - * @return the commit + * @return the owner */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHCommit getCommit() { - return commit; + public GHRepository getOwner() { + return owner; } /** @@ -43,26 +57,12 @@ public String getName() { } /** - * Gets owner. + * Gets commit. * - * @return the owner + * @return the commit */ @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return owner; - } - - /** - * Wrap. - * - * @param owner - * the owner - * @return the GH tag - */ - GHTag wrap(GHRepository owner) { - this.owner = owner; - if (commit != null) - commit.wrapUp(owner); - return this; + public GHCommit getCommit() { + return commit; } } diff --git a/src/main/java/org/kohsuke/github/GHTagObject.java b/src/main/java/org/kohsuke/github/GHTagObject.java index 07f5d9e35e..fbf255e7c3 100644 --- a/src/main/java/org/kohsuke/github/GHTagObject.java +++ b/src/main/java/org/kohsuke/github/GHTagObject.java @@ -12,38 +12,32 @@ justification = "JSON API") public class GHTagObject extends GitHubInteractiveObject { - private String message; - - private GHRef.GHObject object; - - private GHRepository owner; - private String sha; - private String tag; - private GitUser tagger; - private String url; - private GHVerification verification; /** * Create default GHTagObject instance */ public GHTagObject() { } - /** - * Gets message. - * - * @return the message - */ - public String getMessage() { - return message; - } + private GHRepository owner; + + private String tag; + private String sha; + private String url; + private String message; + private GitUser tagger; + private GHRef.GHObject object; + private GHVerification verification; /** - * Gets object. + * Wrap. * - * @return the object + * @param owner + * the owner + * @return the GH tag object */ - public GHRef.GHObject getObject() { - return object; + GHTagObject wrap(GHRepository owner) { + this.owner = owner; + return this; } /** @@ -56,6 +50,15 @@ public GHRepository getOwner() { return owner; } + /** + * Gets tag. + * + * @return the tag + */ + public String getTag() { + return tag; + } + /** * Gets sha. * @@ -66,12 +69,21 @@ public String getSha() { } /** - * Gets tag. + * Gets url. * - * @return the tag + * @return the url */ - public String getTag() { - return tag; + public String getUrl() { + return url; + } + + /** + * Gets message. + * + * @return the message + */ + public String getMessage() { + return message; } /** @@ -84,12 +96,12 @@ public GitUser getTagger() { } /** - * Gets url. + * Gets object. * - * @return the url + * @return the object */ - public String getUrl() { - return url; + public GHRef.GHObject getObject() { + return object; } /** @@ -100,16 +112,4 @@ public String getUrl() { public GHVerification getVerification() { return verification; } - - /** - * Wrap. - * - * @param owner - * the owner - * @return the GH tag object - */ - GHTagObject wrap(GHRepository owner) { - this.owner = owner; - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHTeam.java b/src/main/java/org/kohsuke/github/GHTeam.java index 49be640321..edba5e7b25 100644 --- a/src/main/java/org/kohsuke/github/GHTeam.java +++ b/src/main/java/org/kohsuke/github/GHTeam.java @@ -20,16 +20,36 @@ */ public class GHTeam extends GHObject implements Refreshable { + /** + * Create default GHTeam instance + */ + public GHTeam() { + } + + /** + * Path for external group-related operations + */ + private static final String EXTERNAL_GROUPS = "/external-groups"; + + private String html_url; + private String name; + private String permission; + private String slug; + private String description; + private String privacy; + + private GHOrganization organization; // populated by GET /user/teams where Teams+Orgs are returned together + /** * The Enum Privacy. */ public enum Privacy { + /** The secret. */ + SECRET, /** The closed. */ // only visible to organization owners and members of this team. - CLOSED, - /** The secret. */ - SECRET, // visible to all members of this organization. + CLOSED, // visible to all members of this organization. /** Unknown privacy value */ UNKNOWN } @@ -39,207 +59,143 @@ public enum Privacy { */ public enum Role { + /** A normal member of the team. */ + MEMBER, /** * Able to add/remove other team members, promote other team members to team maintainer, and edit the team's * name and description. */ - MAINTAINER, - /** A normal member of the team. */ - MEMBER + MAINTAINER } /** - * Path for external group-related operations - */ - private static final String EXTERNAL_GROUPS = "/external-groups"; - private String description; - private String htmlUrl; - private String name; - private GHOrganization organization; // populated by GET /user/teams where Teams+Orgs are returned together - private String permission; - - private String privacy; - - private String slug; - - /** - * Create default GHTeam instance + * Wrap up. + * + * @param owner + * the owner + * @return the GH team */ - public GHTeam() { + GHTeam wrapUp(GHOrganization owner) { + this.organization = owner; + return this; } /** - * Add. + * Wrap up. * - * @param r - * the r - * @throws IOException - * the io exception + * @param root + * the root + * @return the GH team */ - public void add(GHRepository r) throws IOException { - add(r, (GHOrganization.RepositoryRole) null); + GHTeam wrapUp(GitHub root) { // auto-wrapUp when organization is known from GET /user/teams + return wrapUp(organization); } /** - * Add. + * Gets name. * - * @param r - * the r - * @param permission - * the permission - * @throws IOException - * the io exception + * @return the name */ - public void add(GHRepository r, GHOrganization.RepositoryRole permission) throws IOException { - root().createRequest() - .method("PUT") - .with("permission", - Optional.ofNullable(permission).map(GHOrganization.RepositoryRole::toString).orElse(null)) - .withUrlPath(api("/repos/" + r.getOwnerName() + '/' + r.getName())) - .send(); + public String getName() { + return name; } /** - * Adds a member to the team. - *

- * The user will be invited to the organization if required. + * Gets permission. * - * @param u - * the u - * @throws IOException - * the io exception - * @since 1.59 + * @return the permission */ - public void add(GHUser u) throws IOException { - root().createRequest().method("PUT").withUrlPath(api("/memberships/" + u.getLogin())).send(); + public String getPermission() { + return permission; } /** - * Adds a member to the team - *

- * The user will be invited to the organization if required. + * Gets slug. * - * @param user - * github user - * @param role - * role for the new member - * @throws IOException - * the io exception + * @return the slug */ - public void add(GHUser user, Role role) throws IOException { - root().createRequest() - .method("PUT") - .with("role", role) - .withUrlPath(api("/memberships/" + user.getLogin())) - .send(); + public String getSlug() { + return slug; } /** - * Connect an external group to the team + * Gets description. * - * @param group - * the group to connect - * @return the external group - * @throws IOException - * in case of failure - * @see documentation + * @return the description */ - public GHExternalGroup connectToExternalGroup(final GHExternalGroup group) throws IOException { - return connectToExternalGroup(group.getId()); + public String getDescription() { + return description; } /** - * Connect an external group to the team + * Gets the privacy state. * - * @param group_id - * the identifier of the group to connect - * @return the external group - * @throws IOException - * in case of failure - * @see documentation + * @return the privacy state. */ - public GHExternalGroup connectToExternalGroup(final long group_id) throws IOException { - try { - return root().createRequest() - .method("PATCH") - .with("group_id", group_id) - .withUrlPath(publicApi(EXTERNAL_GROUPS)) - .fetch(GHExternalGroup.class) - .wrapUp(getOrganization()); - } catch (final HttpException e) { - throw EnterpriseManagedSupport.forOrganization(getOrganization()) - .filterException(e, "Could not connect team to external group") - .orElse(e); - } + public Privacy getPrivacy() { + return EnumUtils.getNullableEnumOrDefault(Privacy.class, privacy, Privacy.UNKNOWN); } /** - * Begins the creation of a new instance. - * - * Consumer must call {@link GHDiscussion.Creator#done()} to commit changes. + * Sets description. * - * @param title - * title of the discussion to be created - * @return a {@link GHDiscussion.Creator} + * @param description + * the description * @throws IOException * the io exception */ - public GHDiscussion.Creator createDiscussion(String title) throws IOException { - return GHDiscussion.create(this).title(title); + public void setDescription(String description) throws IOException { + root().createRequest().method("PATCH").with("description", description).withUrlPath(api("")).send(); } /** - * Deletes this team. + * Updates the team's privacy setting. * + * @param privacy + * the privacy * @throws IOException * the io exception */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(api("")).send(); + public void setPrivacy(Privacy privacy) throws IOException { + root().createRequest().method("PATCH").with("privacy", privacy).withUrlPath(api("")).send(); } /** - * Remove the connection of the team to an external group + * Retrieves the discussions. * + * @return the paged iterable * @throws IOException - * in case of failure - * @see documentation + * the io exception */ - public void deleteExternalGroupConnection() throws IOException { - root().createRequest().method("DELETE").withUrlPath(publicApi(EXTERNAL_GROUPS)).send(); + @Nonnull + public PagedIterable listDiscussions() throws IOException { + return GHDiscussion.readAll(this); } /** - * Equals. + * List members with specified role paged iterable. * - * @param o - * the o - * @return true, if successful + * @param role + * the role + * @return the paged iterable + * @throws IOException + * the io exception */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - GHTeam ghTeam = (GHTeam) o; - return Objects.equals(name, ghTeam.name) && Objects.equals(getUrl(), ghTeam.getUrl()) - && Objects.equals(permission, ghTeam.permission) && Objects.equals(slug, ghTeam.slug) - && Objects.equals(description, ghTeam.description) && Objects.equals(privacy, ghTeam.privacy); + public PagedIterable listMembers(String role) throws IOException { + return root().createRequest().withUrlPath(api("/members")).with("role", role).toIterable(GHUser[].class, null); } /** - * Gets description. + * List members with specified role paged iterable. * - * @return the description + * @param role + * the role + * @return the paged iterable + * @throws IOException + * the io exception */ - public String getDescription() { - return description; + public PagedIterable listMembers(Role role) throws IOException { + return listMembers(transformEnum(role)); } /** @@ -258,35 +214,27 @@ public GHDiscussion getDiscussion(long discussionNumber) throws IOException { } /** - * Get the external groups connected to the team + * Retrieves the current members. * - * @return the external groups + * @return the paged iterable * @throws IOException * the io exception - * @see documentation */ - public List getExternalGroups() throws IOException { - try { - return Collections.unmodifiableList(Arrays.asList(root().createRequest() - .method("GET") - .withUrlPath(publicApi(EXTERNAL_GROUPS)) - .fetch(GHExternalGroupPage.class) - .getGroups())); - } catch (final HttpException e) { - throw EnterpriseManagedSupport.forOrganization(getOrganization()) - .filterException(e, "Could not retrieve team external groups") - .orElse(e); - } + public PagedIterable listMembers() throws IOException { + return listMembers("all"); } /** - * Gets the html url. + * Retrieves the teams that are children of this team. * - * @return the html url + * @return the paged iterable + * @throws IOException + * the io exception */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public PagedIterable listChildTeams() throws IOException { + return root().createRequest() + .withUrlPath(api("/teams")) + .toIterable(GHTeam[].class, item -> item.wrapUp(this.organization)); } /** @@ -301,51 +249,29 @@ public Set getMembers() throws IOException { } /** - * Gets name. + * Checks if this team has the specified user as a member. * - * @return the name + * @param user + * the user + * @return the boolean */ - public String getName() { - return name; - } - - /** - * Gets organization. - * - * @return the organization - * @throws IOException - * the io exception - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHOrganization getOrganization() throws IOException { - refresh(organization); - return organization; - } - - /** - * Gets permission. - * - * @return the permission - */ - public String getPermission() { - return permission; - } - - /** - * Gets the privacy state. - * - * @return the privacy state. - */ - public Privacy getPrivacy() { - return EnumUtils.getNullableEnumOrDefault(Privacy.class, privacy, Privacy.UNKNOWN); + public boolean hasMember(GHUser user) { + try { + root().createRequest().withUrlPath(api("/memberships/" + user.getLogin())).send(); + return true; + } catch (@SuppressWarnings("unused") IOException ignore) { + return false; + } } /** * Gets repositories. * * @return the repositories + * @throws IOException + * the io exception */ - public Map getRepositories() { + public Map getRepositories() throws IOException { Map m = new TreeMap<>(); for (GHRepository r : listRepositories()) { m.put(r.getName(), r); @@ -354,198 +280,284 @@ public Map getRepositories() { } /** - * Gets slug. + * List repositories paged iterable. * - * @return the slug + * @return the paged iterable */ - public String getSlug() { - return slug; + public PagedIterable listRepositories() { + return root().createRequest().withUrlPath(api("/repos")).toIterable(GHRepository[].class, null); } /** - * Checks if this team has the specified user as a member. + * Adds a member to the team. + *

+ * The user will be invited to the organization if required. * - * @param user - * the user - * @return the boolean + * @param u + * the u + * @throws IOException + * the io exception + * @since 1.59 */ - public boolean hasMember(GHUser user) { - try { - root().createRequest().withUrlPath(api("/memberships/" + user.getLogin())).send(); - return true; - } catch (@SuppressWarnings("unused") IOException ignore) { - return false; - } + public void add(GHUser u) throws IOException { + root().createRequest().method("PUT").withUrlPath(api("/memberships/" + u.getLogin())).send(); } /** - * Hash code. + * Adds a member to the team + *

+ * The user will be invited to the organization if required. * - * @return the int + * @param user + * github user + * @param role + * role for the new member + * @throws IOException + * the io exception */ - @Override - public int hashCode() { - return Objects.hash(name, getUrl(), permission, slug, description, privacy); + public void add(GHUser user, Role role) throws IOException { + root().createRequest() + .method("PUT") + .with("role", role) + .withUrlPath(api("/memberships/" + user.getLogin())) + .send(); } /** - * Retrieves the teams that are children of this team. + * Removes a member to the team. * - * @return the paged iterable + * @param u + * the u + * @throws IOException + * the io exception */ - public PagedIterable listChildTeams() { - return root().createRequest() - .withUrlPath(api("/teams")) - .toIterable(GHTeam[].class, item -> item.wrapUp(this.organization)); + public void remove(GHUser u) throws IOException { + root().createRequest().method("DELETE").withUrlPath(api("/memberships/" + u.getLogin())).send(); } /** - * Retrieves the discussions. + * Add. * - * @return the paged iterable + * @param r + * the r + * @throws IOException + * the io exception */ - @Nonnull - public PagedIterable listDiscussions() { - return GHDiscussion.readAll(this); + public void add(GHRepository r) throws IOException { + add(r, (GHOrganization.RepositoryRole) null); } /** - * Retrieves the current members. + * Add. * - * @return the paged iterable + * @param r + * the r + * @param permission + * the permission + * @throws IOException + * the io exception */ - public PagedIterable listMembers() { - return listMembers("all"); + public void add(GHRepository r, GHOrganization.RepositoryRole permission) throws IOException { + root().createRequest() + .method("PUT") + .with("permission", + Optional.ofNullable(permission).map(GHOrganization.RepositoryRole::toString).orElse(null)) + .withUrlPath(api("/repos/" + r.getOwnerName() + '/' + r.getName())) + .send(); } /** - * List members with specified role paged iterable. + * Remove. * - * @param role - * the role - * @return the paged iterable + * @param r + * the r + * @throws IOException + * the io exception */ - public PagedIterable listMembers(Role role) { - return listMembers(transformEnum(role)); + public void remove(GHRepository r) throws IOException { + root().createRequest() + .method("DELETE") + .withUrlPath(api("/repos/" + r.getOwnerName() + '/' + r.getName())) + .send(); } /** - * List members with specified role paged iterable. + * Deletes this team. * - * @param role - * the role - * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listMembers(String role) { - return root().createRequest().withUrlPath(api("/members")).with("role", role).toIterable(GHUser[].class, null); + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(api("")).send(); + } + + private String api(String tail) { + if (organization == null) { + // Teams returned from pull requests to do not have an organization. Attempt to use url. + final URL url = Objects.requireNonNull(getUrl(), "Missing instance URL!"); + return StringUtils.prependIfMissing(url.toString().replace(root().getApiUrl(), ""), "/") + tail; + } + + return "/organizations/" + organization.getId() + "/team/" + getId() + tail; + } + + private String publicApi(String tail) throws IOException { + return "/orgs/" + getOrganization().login + "/teams/" + getSlug() + tail; } /** - * List repositories paged iterable. + * Begins the creation of a new instance. * - * @return the paged iterable + * Consumer must call {@link GHDiscussion.Creator#done()} to commit changes. + * + * @param title + * title of the discussion to be created + * @return a {@link GHDiscussion.Creator} + * @throws IOException + * the io exception */ - public PagedIterable listRepositories() { - return root().createRequest().withUrlPath(api("/repos")).toIterable(GHRepository[].class, null); + public GHDiscussion.Creator createDiscussion(String title) throws IOException { + return GHDiscussion.create(this).title(title); } /** - * Refresh. + * Get the external groups connected to the team * + * @return the external groups * @throws IOException - * Signals that an I/O exception has occurred. + * the io exception + * @see documentation */ - @Override - public void refresh() throws IOException { - root().createRequest().withUrlPath(api("")).fetchInto(this).wrapUp(root()); + public List getExternalGroups() throws IOException { + try { + return Collections.unmodifiableList(Arrays.asList(root().createRequest() + .method("GET") + .withUrlPath(publicApi(EXTERNAL_GROUPS)) + .fetch(GHExternalGroupPage.class) + .getGroups())); + } catch (final HttpException e) { + throw EnterpriseManagedSupport.forOrganization(getOrganization()) + .filterException(e, "Could not retrieve team external groups") + .orElse(e); + } } /** - * Remove. + * Connect an external group to the team * - * @param r - * the r + * @param group + * the group to connect + * @return the external group * @throws IOException - * the io exception + * in case of failure + * @see documentation */ - public void remove(GHRepository r) throws IOException { - root().createRequest() - .method("DELETE") - .withUrlPath(api("/repos/" + r.getOwnerName() + '/' + r.getName())) - .send(); + public GHExternalGroup connectToExternalGroup(final GHExternalGroup group) throws IOException { + return connectToExternalGroup(group.getId()); } /** - * Removes a member to the team. + * Connect an external group to the team * - * @param u - * the u + * @param group_id + * the identifier of the group to connect + * @return the external group * @throws IOException - * the io exception + * in case of failure + * @see documentation */ - public void remove(GHUser u) throws IOException { - root().createRequest().method("DELETE").withUrlPath(api("/memberships/" + u.getLogin())).send(); + public GHExternalGroup connectToExternalGroup(final long group_id) throws IOException { + try { + return root().createRequest() + .method("PATCH") + .with("group_id", group_id) + .withUrlPath(publicApi(EXTERNAL_GROUPS)) + .fetch(GHExternalGroup.class) + .wrapUp(getOrganization()); + } catch (final HttpException e) { + throw EnterpriseManagedSupport.forOrganization(getOrganization()) + .filterException(e, "Could not connect team to external group") + .orElse(e); + } } /** - * Sets description. + * Remove the connection of the team to an external group * - * @param description - * the description * @throws IOException - * the io exception + * in case of failure + * @see documentation */ - public void setDescription(String description) throws IOException { - root().createRequest().method("PATCH").with("description", description).withUrlPath(api("")).send(); + public void deleteExternalGroupConnection() throws IOException { + root().createRequest().method("DELETE").withUrlPath(publicApi(EXTERNAL_GROUPS)).send(); } /** - * Updates the team's privacy setting. + * Gets organization. * - * @param privacy - * the privacy + * @return the organization * @throws IOException * the io exception */ - public void setPrivacy(Privacy privacy) throws IOException { - root().createRequest().method("PATCH").with("privacy", privacy).withUrlPath(api("")).send(); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHOrganization getOrganization() throws IOException { + refresh(organization); + return organization; } - private String api(String tail) { - if (organization == null) { - // Teams returned from pull requests to do not have an organization. Attempt to use url. - final URL url = Objects.requireNonNull(getUrl(), "Missing instance URL!"); - return StringUtils.prependIfMissing(url.toString().replace(root().getApiUrl(), ""), "/") + tail; - } - - return "/organizations/" + organization.getId() + "/team/" + getId() + tail; + /** + * Refresh. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Override + public void refresh() throws IOException { + root().createRequest().withUrlPath(api("")).fetchInto(this).wrapUp(root()); } - private String publicApi(String tail) throws IOException { - return "/orgs/" + getOrganization().login + "/teams/" + getSlug() + tail; + /** + * Gets the html url. + * + * @return the html url + */ + public URL getHtmlUrl() { + return GitHubClient.parseURL(html_url); } /** - * Wrap up. + * Equals. * - * @param owner - * the owner - * @return the GH team + * @param o + * the o + * @return true, if successful */ - GHTeam wrapUp(GHOrganization owner) { - this.organization = owner; - return this; + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GHTeam ghTeam = (GHTeam) o; + return Objects.equals(name, ghTeam.name) && Objects.equals(getUrl(), ghTeam.getUrl()) + && Objects.equals(permission, ghTeam.permission) && Objects.equals(slug, ghTeam.slug) + && Objects.equals(description, ghTeam.description) && Objects.equals(privacy, ghTeam.privacy); } /** - * Wrap up. + * Hash code. * - * @param root - * the root - * @return the GH team + * @return the int */ - GHTeam wrapUp(GitHub root) { // auto-wrapUp when organization is known from GET /user/teams - return wrapUp(organization); + @Override + public int hashCode() { + return Objects.hash(name, getUrl(), permission, slug, description, privacy); } } diff --git a/src/main/java/org/kohsuke/github/GHTeamBuilder.java b/src/main/java/org/kohsuke/github/GHTeamBuilder.java index 12d077d974..6db44008af 100644 --- a/src/main/java/org/kohsuke/github/GHTeamBuilder.java +++ b/src/main/java/org/kohsuke/github/GHTeamBuilder.java @@ -12,9 +12,9 @@ */ public class GHTeamBuilder extends GitHubInteractiveObject { - private final String orgName; /** The builder. */ protected final Requester builder; + private final String orgName; /** * Instantiates a new GH team builder. @@ -34,17 +34,6 @@ public GHTeamBuilder(GitHub root, String orgName, String name) { this.builder.with("name", name); } - /** - * Creates a team with all the parameters. - * - * @return the gh team - * @throws IOException - * if team cannot be created - */ - public GHTeam create() throws IOException { - return builder.method("POST").withUrlPath("/orgs/" + orgName + "/teams").fetch(GHTeam.class).wrapUp(root()); - } - /** * Description for this team. * @@ -70,14 +59,14 @@ public GHTeamBuilder maintainers(String... maintainers) { } /** - * Parent team id for this team. + * Repository names to add this team to. * - * @param parentTeamId - * parentTeamId of team + * @param repoNames + * repoNames to add team to * @return a builder to continue with building */ - public GHTeamBuilder parentTeamId(long parentTeamId) { - this.builder.with("parent_team_id", parentTeamId); + public GHTeamBuilder repositories(String... repoNames) { + this.builder.with("repo_names", repoNames); return this; } @@ -109,14 +98,25 @@ public GHTeamBuilder privacy(GHTeam.Privacy privacy) { } /** - * Repository names to add this team to. + * Parent team id for this team. * - * @param repoNames - * repoNames to add team to + * @param parentTeamId + * parentTeamId of team * @return a builder to continue with building */ - public GHTeamBuilder repositories(String... repoNames) { - this.builder.with("repo_names", repoNames); + public GHTeamBuilder parentTeamId(long parentTeamId) { + this.builder.with("parent_team_id", parentTeamId); return this; } + + /** + * Creates a team with all the parameters. + * + * @return the gh team + * @throws IOException + * if team cannot be created + */ + public GHTeam create() throws IOException { + return builder.method("POST").withUrlPath("/orgs/" + orgName + "/teams").fetch(GHTeam.class).wrapUp(root()); + } } diff --git a/src/main/java/org/kohsuke/github/GHTeamChanges.java b/src/main/java/org/kohsuke/github/GHTeamChanges.java index 8aafac1e4e..30962bd3bf 100644 --- a/src/main/java/org/kohsuke/github/GHTeamChanges.java +++ b/src/main/java/org/kohsuke/github/GHTeamChanges.java @@ -15,18 +15,88 @@ public class GHTeamChanges { /** - * Changes made to privacy. + * Create default GHTeamChanges instance */ - public static class FromPrivacy { + public GHTeamChanges() { + } + + private FromString description; + private FromString name; + private FromPrivacy privacy; + private FromRepository repository; + + /** + * Gets changes to description. + * + * @return changes to description. + */ + public FromString getDescription() { + return description; + } + + /** + * Gets changes to name. + * + * @return changes to name. + */ + public FromString getName() { + return name; + } + + /** + * Gets changes to privacy. + * + * @return changes to privacy. + */ + public FromPrivacy getPrivacy() { + return privacy; + } + + /** + * Gets changes for repository events. + * + * @return changes for repository events. + */ + public FromRepository getRepository() { + return repository; + } + + /** + * Changes made to a string value. + */ + public static class FromString { + + /** + * Create default FromString instance + */ + public FromString() { + } private String from; + /** + * Gets the from. + * + * @return the from + */ + public String getFrom() { + return from; + } + } + + /** + * Changes made to privacy. + */ + public static class FromPrivacy { + /** * Create default FromPrivacy instance */ public FromPrivacy() { } + private String from; + /** * Gets the from. * @@ -42,14 +112,14 @@ public Privacy getFrom() { */ public static class FromRepository { - private FromRepositoryPermissions permissions; - /** * Create default FromRepository instance */ public FromRepository() { } + private FromRepositoryPermissions permissions; + /** * Gets the changes to permissions. * @@ -59,27 +129,19 @@ public FromRepositoryPermissions getPermissions() { return permissions; } } + /** * Changes made to permissions. */ public static class FromRepositoryPermissions { - private GHRepoPermission from; - /** * Create default FromRepositoryPermissions instance */ public FromRepositoryPermissions() { } - /** - * Has admin access boolean. - * - * @return the boolean - */ - public boolean hadAdminAccess() { - return from != null && from.admin; - } + private GHRepoPermission from; /** * Has pull access boolean. @@ -98,76 +160,14 @@ public boolean hadPullAccess() { public boolean hadPushAccess() { return from != null && from.push; } - } - /** - * Changes made to a string value. - */ - public static class FromString { - - private String from; - - /** - * Create default FromString instance - */ - public FromString() { - } /** - * Gets the from. + * Has admin access boolean. * - * @return the from + * @return the boolean */ - public String getFrom() { - return from; + public boolean hadAdminAccess() { + return from != null && from.admin; } } - private FromString description; - - private FromString name; - - private FromPrivacy privacy; - - private FromRepository repository; - - /** - * Create default GHTeamChanges instance - */ - public GHTeamChanges() { - } - - /** - * Gets changes to description. - * - * @return changes to description. - */ - public FromString getDescription() { - return description; - } - - /** - * Gets changes to name. - * - * @return changes to name. - */ - public FromString getName() { - return name; - } - - /** - * Gets changes to privacy. - * - * @return changes to privacy. - */ - public FromPrivacy getPrivacy() { - return privacy; - } - - /** - * Gets changes for repository events. - * - * @return changes for repository events. - */ - public FromRepository getRepository() { - return repository; - } } diff --git a/src/main/java/org/kohsuke/github/GHThread.java b/src/main/java/org/kohsuke/github/GHThread.java index 5e577aa75b..2bafc28307 100644 --- a/src/main/java/org/kohsuke/github/GHThread.java +++ b/src/main/java/org/kohsuke/github/GHThread.java @@ -1,11 +1,9 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.FileNotFoundException; import java.io.IOException; -import java.time.Instant; import java.util.Date; // TODO: Auto-generated Javadoc @@ -19,82 +17,32 @@ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") public class GHThread extends GHObject { + private GHRepository repository; + private Subject subject; + private String reason; + private boolean unread; + private String last_read_at; + private String url, subscription_url; + /** * The Class Subject. */ - static class Subject extends GitHubBridgeAdapterObject { - - /** The latest comment url. */ - String latestCommentUrl; + static class Subject { /** The title. */ String title; - /** The type. */ - String type; - /** The url. */ String url; - } - private String lastReadAt; - private String reason; - private GHRepository repository; - private Subject subject; - private boolean unread; - - private String url, subscriptionUrl; - - private GHThread() {// no external construction allowed - } - - /** - * If this thread is about a commit, return that commit. - * - * @return null if this thread is not about a commit. - * @throws IOException - * the io exception - */ - public GHCommit getBoundCommit() throws IOException { - if (!"Commit".equals(subject.type)) - return null; - return repository.getCommit(subject.url.substring(subject.url.lastIndexOf('/') + 1)); - } - /** - * If this thread is about an issue, return that issue. - * - * @return null if this thread is not about an issue. - * @throws IOException - * the io exception - */ - public GHIssue getBoundIssue() throws IOException { - if (!"Issue".equals(subject.type) && "PullRequest".equals(subject.type)) - return null; - return repository.getIssue(Integer.parseInt(subject.url.substring(subject.url.lastIndexOf('/') + 1))); - } + /** The latest comment url. */ + String latest_comment_url; - /** - * If this thread is about a pull request, return that pull request. - * - * @return null if this thread is not about a pull request. - * @throws IOException - * the io exception - */ - public GHPullRequest getBoundPullRequest() throws IOException { - if (!"PullRequest".equals(subject.type)) - return null; - return repository.getPullRequest(Integer.parseInt(subject.url.substring(subject.url.lastIndexOf('/') + 1))); + /** The type. */ + String type; } - // TODO: how to expose the subject? - - /** - * Gets last comment url. - * - * @return the last comment url - */ - public String getLastCommentUrl() { - return subject.latestCommentUrl; + private GHThread() {// no external construction allowed } /** @@ -102,9 +50,8 @@ public String getLastCommentUrl() { * * @return the last read at */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getLastReadAt() { - return GitHubClient.parseInstant(lastReadAt); + public Date getLastReadAt() { + return GitHubClient.parseDate(last_read_at); } /** @@ -126,19 +73,15 @@ public GHRepository getRepository() { return repository; } + // TODO: how to expose the subject? + /** - * Returns the current subscription for this thread. + * Is read boolean. * - * @return null if no subscription exists. - * @throws IOException - * the io exception + * @return the boolean */ - public GHSubscription getSubscription() throws IOException { - try { - return root().createRequest().method("POST").withUrlPath(subscriptionUrl).fetch(GHSubscription.class); - } catch (FileNotFoundException e) { - return null; - } + public boolean isRead() { + return !unread; } /** @@ -160,12 +103,51 @@ public String getType() { } /** - * Is read boolean. + * Gets last comment url. * - * @return the boolean + * @return the last comment url */ - public boolean isRead() { - return !unread; + public String getLastCommentUrl() { + return subject.latest_comment_url; + } + + /** + * If this thread is about an issue, return that issue. + * + * @return null if this thread is not about an issue. + * @throws IOException + * the io exception + */ + public GHIssue getBoundIssue() throws IOException { + if (!"Issue".equals(subject.type) && "PullRequest".equals(subject.type)) + return null; + return repository.getIssue(Integer.parseInt(subject.url.substring(subject.url.lastIndexOf('/') + 1))); + } + + /** + * If this thread is about a pull request, return that pull request. + * + * @return null if this thread is not about a pull request. + * @throws IOException + * the io exception + */ + public GHPullRequest getBoundPullRequest() throws IOException { + if (!"PullRequest".equals(subject.type)) + return null; + return repository.getPullRequest(Integer.parseInt(subject.url.substring(subject.url.lastIndexOf('/') + 1))); + } + + /** + * If this thread is about a commit, return that commit. + * + * @return null if this thread is not about a commit. + * @throws IOException + * the io exception + */ + public GHCommit getBoundCommit() throws IOException { + if (!"Commit".equals(subject.type)) + return null; + return repository.getCommit(subject.url.substring(subject.url.lastIndexOf('/') + 1)); } /** @@ -194,7 +176,22 @@ public GHSubscription subscribe(boolean subscribed, boolean ignored) throws IOEx .method("PUT") .with("subscribed", subscribed) .with("ignored", ignored) - .withUrlPath(subscriptionUrl) + .withUrlPath(subscription_url) .fetch(GHSubscription.class); } + + /** + * Returns the current subscription for this thread. + * + * @return null if no subscription exists. + * @throws IOException + * the io exception + */ + public GHSubscription getSubscription() throws IOException { + try { + return root().createRequest().method("POST").withUrlPath(subscription_url).fetch(GHSubscription.class); + } catch (FileNotFoundException e) { + return null; + } + } } diff --git a/src/main/java/org/kohsuke/github/GHTree.java b/src/main/java/org/kohsuke/github/GHTree.java index 281d161b5b..867fa4531d 100644 --- a/src/main/java/org/kohsuke/github/GHTree.java +++ b/src/main/java/org/kohsuke/github/GHTree.java @@ -20,35 +20,18 @@ justification = "JSON API") public class GHTree { - private String sha, url; - - private GHTreeEntry[] tree; - - private boolean truncated; - /** The repo. */ - /* package almost final */GHRepository repo; /** * Create default GHTree instance */ public GHTree() { } - /** - * Finds a tree entry by its name. - *

- * IOW, find a directory entry by a file name. - * - * @param path - * the path - * @return the entry - */ - public GHTreeEntry getEntry(String path) { - for (GHTreeEntry e : tree) { - if (e.getPath().equals(path)) - return e; - } - return null; - } + /** The repo. */ + /* package almost final */GHRepository repo; + + private boolean truncated; + private String sha, url; + private GHTreeEntry[] tree; /** * The SHA for this trees. @@ -69,13 +52,20 @@ public List getTree() { } /** - * The API URL of this tag, such as "url": - * "https://api.github.com/repos/octocat/Hello-World/trees/fc6274d15fa3ae2ab983129fb037999f264ba9a7", + * Finds a tree entry by its name. + *

+ * IOW, find a directory entry by a file name. * - * @return the url + * @param path + * the path + * @return the entry */ - public URL getUrl() { - return GitHubClient.parseURL(url); + public GHTreeEntry getEntry(String path) { + for (GHTreeEntry e : tree) { + if (e.getPath().equals(path)) + return e; + } + return null; } /** @@ -87,6 +77,16 @@ public boolean isTruncated() { return truncated; } + /** + * The API URL of this tag, such as "url": + * "https://api.github.com/repos/octocat/Hello-World/trees/fc6274d15fa3ae2ab983129fb037999f264ba9a7", + * + * @return the url + */ + public URL getUrl() { + return GitHubClient.parseURL(url); + } + /** * Wrap. * diff --git a/src/main/java/org/kohsuke/github/GHTreeBuilder.java b/src/main/java/org/kohsuke/github/GHTreeBuilder.java index c771e60650..c7e1902124 100644 --- a/src/main/java/org/kohsuke/github/GHTreeBuilder.java +++ b/src/main/java/org/kohsuke/github/GHTreeBuilder.java @@ -14,31 +14,21 @@ * Builder pattern for creating a new tree. Based on https://developer.github.com/v3/git/trees/#create-a-tree */ public class GHTreeBuilder { - private static class DeleteTreeEntry extends TreeEntry { - /** - * According to reference doc https://docs.github.com/en/rest/git/trees?apiVersion=2022-11-28#create-a-tree: if - * sha value is null then the file will be deleted. That's why in this DTO sha is always {@literal null} and is - * included to json. - */ - @JsonInclude - private final String sha = null; + private final GHRepository repo; + private final Requester req; + + private final List treeEntries = new ArrayList(); - private DeleteTreeEntry(String path) { - // The `mode` and `type` parameters are required by the API, but their values are ignored during delete. - // Supply reasonable placeholders. - super(path, "100644", "blob"); - } - } // Issue #636: Create Tree no longer accepts null value in sha field @JsonInclude(Include.NON_NULL) @SuppressFBWarnings("URF_UNREAD_FIELD") private static class TreeEntry { - private String content; - private final String mode; private final String path; - private String sha; + private final String mode; private final String type; + private String sha; + private String content; private TreeEntry(String path, String mode, String type) { this.path = path; @@ -47,11 +37,21 @@ private TreeEntry(String path, String mode, String type) { } } - private final GHRepository repo; - - private final Requester req; + private static class DeleteTreeEntry extends TreeEntry { + /** + * According to reference doc https://docs.github.com/en/rest/git/trees?apiVersion=2022-11-28#create-a-tree: if + * sha value is null then the file will be deleted. That's why in this DTO sha is always {@literal null} and is + * included to json. + */ + @JsonInclude + private final String sha = null; - private final List treeEntries = new ArrayList(); + private DeleteTreeEntry(String path) { + // The `mode` and `type` parameters are required by the API, but their values are ignored during delete. + // Supply reasonable placeholders. + super(path, "100644", "blob"); + } + } /** * Instantiates a new GH tree builder. @@ -64,41 +64,6 @@ private TreeEntry(String path, String mode, String type) { req = repo.root().createRequest(); } - /** - * Adds a new entry with the given text content to the tree. - * - * @param path - * the file path in the tree - * @param content - * the file content as UTF-8 encoded string - * @param executable - * true, if the file should be executable - * @return this GHTreeBuilder - */ - public GHTreeBuilder add(String path, String content, boolean executable) { - return add(path, content.getBytes(StandardCharsets.UTF_8), executable); - } - - /** - * Adds a new entry with the given binary content to the tree. - * - * @param path - * the file path in the tree - * @param content - * the file content as byte array - * @param executable - * true, if the file should be executable - * @return this GHTreeBuilder - */ - public GHTreeBuilder add(String path, byte[] content, boolean executable) { - try { - String dataSha = repo.createBlob().binaryContent(content).create().getSha(); - return shaEntry(path, dataSha, executable); - } catch (IOException e) { - throw new GHException("Cannot create binary content of '" + path + "'", e); - } - } - /** * Base tree gh tree builder. * @@ -111,31 +76,6 @@ public GHTreeBuilder baseTree(String baseTree) { return this; } - /** - * Creates a tree based on the parameters specified thus far. - * - * @return the gh tree - * @throws IOException - * the io exception - */ - public GHTree create() throws IOException { - req.with("tree", treeEntries); - return req.method("POST").withUrlPath(getApiTail()).fetch(GHTree.class).wrap(repo); - } - - /** - * Removes an entry with the given path from base tree. - * - * @param path - * the file path in the tree - * @return this GHTreeBuilder - */ - public GHTreeBuilder delete(String path) { - TreeEntry entry = new DeleteTreeEntry(path); - treeEntries.add(entry); - return this; - } - /** * Specialized version of entry() for adding an existing blob referred by its SHA. * @@ -176,7 +116,67 @@ public GHTreeBuilder textEntry(String path, String content, boolean executable) return this; } + /** + * Adds a new entry with the given binary content to the tree. + * + * @param path + * the file path in the tree + * @param content + * the file content as byte array + * @param executable + * true, if the file should be executable + * @return this GHTreeBuilder + */ + public GHTreeBuilder add(String path, byte[] content, boolean executable) { + try { + String dataSha = repo.createBlob().binaryContent(content).create().getSha(); + return shaEntry(path, dataSha, executable); + } catch (IOException e) { + throw new GHException("Cannot create binary content of '" + path + "'", e); + } + } + + /** + * Adds a new entry with the given text content to the tree. + * + * @param path + * the file path in the tree + * @param content + * the file content as UTF-8 encoded string + * @param executable + * true, if the file should be executable + * @return this GHTreeBuilder + */ + public GHTreeBuilder add(String path, String content, boolean executable) { + return add(path, content.getBytes(StandardCharsets.UTF_8), executable); + } + + /** + * Removes an entry with the given path from base tree. + * + * @param path + * the file path in the tree + * @return this GHTreeBuilder + */ + public GHTreeBuilder delete(String path) { + TreeEntry entry = new DeleteTreeEntry(path); + treeEntries.add(entry); + return this; + } + private String getApiTail() { return String.format("/repos/%s/%s/git/trees", repo.getOwnerName(), repo.getName()); } + + /** + * Creates a tree based on the parameters specified thus far. + * + * @return the gh tree + * @throws IOException + * the io exception + */ + public GHTree create() throws IOException { + req.with("tree", treeEntries); + return req.method("POST").withUrlPath(getApiTail()).fetch(GHTree.class).wrap(repo); + } } diff --git a/src/main/java/org/kohsuke/github/GHTreeEntry.java b/src/main/java/org/kohsuke/github/GHTreeEntry.java index a89bb432ff..6759378e1f 100644 --- a/src/main/java/org/kohsuke/github/GHTreeEntry.java +++ b/src/main/java/org/kohsuke/github/GHTreeEntry.java @@ -13,54 +13,17 @@ */ public class GHTreeEntry { - private String path, mode, type, sha, url; - - private long size; - - /** The tree. */ - /* package almost final */GHTree tree; /** * Create default GHTreeEntry instance */ public GHTreeEntry() { } - /** - * If this tree entry represents a file, then return its information. Otherwise null. - * - * @return the gh blob - * @throws IOException - * the io exception - */ - public GHBlob asBlob() throws IOException { - if (type.equals("blob")) - return tree.repo.getBlob(sha); - else - return null; - } - - /** - * If this tree entry represents a directory, then return it. Otherwise null. - * - * @return the gh tree - * @throws IOException - * the io exception - */ - public GHTree asTree() throws IOException { - if (type.equals("tree")) - return tree.repo.getTree(sha); - else - return null; - } + /** The tree. */ + /* package almost final */GHTree tree; - /** - * Get mode such as 100644. - * - * @return the mode - */ - public String getMode() { - return mode; - } + private String path, mode, type, sha, url; + private long size; /** * Get the path such as "subdir/file.txt" @@ -72,12 +35,12 @@ public String getPath() { } /** - * SHA1 of this object. + * Get mode such as 100644. * - * @return the sha + * @return the mode */ - public String getSha() { - return sha; + public String getMode() { + return mode; } /** @@ -98,6 +61,15 @@ public String getType() { return type; } + /** + * SHA1 of this object. + * + * @return the sha + */ + public String getSha() { + return sha; + } + /** * API URL to this Git data, such as https://api.github.com/repos/jenkinsci * /jenkins/git/commits/b72322675eb0114363a9a86e9ad5a170d1d07ac0 @@ -108,6 +80,20 @@ public URL getUrl() { return GitHubClient.parseURL(url); } + /** + * If this tree entry represents a file, then return its information. Otherwise null. + * + * @return the gh blob + * @throws IOException + * the io exception + */ + public GHBlob asBlob() throws IOException { + if (type.equals("blob")) + return tree.repo.getBlob(sha); + else + return null; + } + /** * If this tree entry represents a file, then return its content. Otherwise null. * @@ -121,4 +107,18 @@ public InputStream readAsBlob() throws IOException { else return null; } + + /** + * If this tree entry represents a directory, then return it. Otherwise null. + * + * @return the gh tree + * @throws IOException + * the io exception + */ + public GHTree asTree() throws IOException { + if (type.equals("tree")) + return tree.repo.getTree(sha); + else + return null; + } } diff --git a/src/main/java/org/kohsuke/github/GHUser.java b/src/main/java/org/kohsuke/github/GHUser.java index e1a74beedb..fd93a00937 100644 --- a/src/main/java/org/kohsuke/github/GHUser.java +++ b/src/main/java/org/kohsuke/github/GHUser.java @@ -23,10 +23,7 @@ */ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; - import java.io.IOException; -import java.time.Instant; import java.util.*; // TODO: Auto-generated Javadoc @@ -37,32 +34,27 @@ */ public class GHUser extends GHPerson { - /** The suspendedAt */ - private String suspendedAt; - - /** The ldap dn. */ - protected String ldapDn; - /** * Create default GHUser instance */ public GHUser() { } + /** The ldap dn. */ + protected String ldap_dn; + + /** The suspended_at */ + private String suspendedAt; + /** - * Equals. + * Gets keys. * - * @param obj - * the obj - * @return true, if successful + * @return the keys + * @throws IOException + * the io exception */ - @Override - public boolean equals(Object obj) { - if (obj instanceof GHUser) { - GHUser that = (GHUser) obj; - return this.login.equals(that.login); - } - return false; + public List getKeys() throws IOException { + return root().createRequest().withUrlPath(getApiTailUrl("keys")).toIterable(GHKey[].class, null).toList(); } /** @@ -76,23 +68,13 @@ public void follow() throws IOException { } /** - * Gets the bio. - * - * @return the bio - */ - public String getBio() { - return bio; - } - - /** - * Lists the users who are following this user. + * Unfollow this user. * - * @return the followers * @throws IOException * the io exception */ - public GHPersonSet getFollowers() throws IOException { - return new GHPersonSet(listFollowers().toList()); + public void unfollow() throws IOException { + root().createRequest().method("DELETE").withUrlPath("/user/following/" + login).send(); } /** @@ -107,81 +89,71 @@ public GHPersonSet getFollows() throws IOException { } /** - * Gets keys. + * Lists the users that this user is following. * - * @return the keys - * @throws IOException - * the io exception + * @return the paged iterable */ - public List getKeys() throws IOException { - return root().createRequest().withUrlPath(getApiTailUrl("keys")).toIterable(GHKey[].class, null).toList(); + public PagedIterable listFollows() { + return listUser("following"); } /** - * Gets LDAP information for user. + * Lists the users who are following this user. * - * @return The LDAP information + * @return the followers * @throws IOException * the io exception - * @see Github - * LDAP */ - public Optional getLdapDn() throws IOException { - super.populate(); - return Optional.ofNullable(ldapDn); + public GHPersonSet getFollowers() throws IOException { + return new GHPersonSet(listFollowers().toList()); } /** - * Gets the organization that this user belongs to publicly. + * Lists the users who are following this user. * - * @return the organizations - * @throws IOException - * the io exception + * @return the paged iterable */ - public GHPersonSet getOrganizations() throws IOException { - GHPersonSet orgs = new GHPersonSet(); - Set names = new HashSet(); - for (GHOrganization o : root().createRequest() - .withUrlPath("/users/" + login + "/orgs") - .toIterable(GHOrganization[].class, null) - .toArray()) { - if (names.add(o.getLogin())) // I've seen some duplicates in the data - orgs.add(root().getOrganization(o.getLogin())); - } - return orgs; + public PagedIterable listFollowers() { + return listUser("followers"); + } + + private PagedIterable listUser(final String suffix) { + return root().createRequest().withUrlPath(getApiTailUrl(suffix)).toIterable(GHUser[].class, null); } /** - * When was this user suspended?. + * Lists all the subscribed (aka watched) repositories. + *

+ * https://developer.github.com/v3/activity/watching/ * - * @return updated date - * @throws IOException - * on error + * @return the paged iterable */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getSuspendedAt() throws IOException { - super.populate(); - return GitHubClient.parseInstant(suspendedAt); + public PagedIterable listSubscriptions() { + return listRepositories("subscriptions"); } /** - * Hash code. + * Lists all the repositories that this user has starred. * - * @return the int + * @return the paged iterable */ - @Override - public int hashCode() { - return login.hashCode(); + public PagedIterable listStarredRepositories() { + return listRepositories("starred"); } /** - * Returns true if this user is marked as hireable, false otherwise. + * Lists all the projects. + *

+ * https://docs.github.com/en/rest/reference/projects#list-user-projects * - * @return if the user is marked as hireable + * @return the paged iterable */ - public boolean isHireable() { - return hireable; + public PagedIterable listProjects() { + return root().createRequest().withUrlPath(getApiTailUrl("projects")).toIterable(GHProject[].class, null); + } + + private PagedIterable listRepositories(final String suffix) { + return root().createRequest().withUrlPath(getApiTailUrl(suffix)).toIterable(GHRepository[].class, null); } /** @@ -218,94 +190,120 @@ public boolean isPublicMemberOf(GHOrganization org) { } /** - * Lists events performed by a user (this includes private events if the caller is authenticated. + * Returns true if this user is marked as hireable, false otherwise. * - * @return the paged iterable - * @throws IOException - * Signals that an I/O exception has occurred. + * @return if the user is marked as hireable */ - public PagedIterable listEvents() throws IOException { - return root().createRequest() - .withUrlPath(String.format("/users/%s/events", login)) - .toIterable(GHEventInfo[].class, null); + public boolean isHireable() { + return hireable; } /** - * Lists the users who are following this user. + * Gets the bio. * - * @return the paged iterable + * @return the bio */ - public PagedIterable listFollowers() { - return listUser("followers"); + public String getBio() { + return bio; } /** - * Lists the users that this user is following. + * Gets the organization that this user belongs to publicly. + * + * @return the organizations + * @throws IOException + * the io exception + */ + public GHPersonSet getOrganizations() throws IOException { + GHPersonSet orgs = new GHPersonSet(); + Set names = new HashSet(); + for (GHOrganization o : root().createRequest() + .withUrlPath("/users/" + login + "/orgs") + .toIterable(GHOrganization[].class, null) + .toArray()) { + if (names.add(o.getLogin())) // I've seen some duplicates in the data + orgs.add(root().getOrganization(o.getLogin())); + } + return orgs; + } + + /** + * Lists events performed by a user (this includes private events if the caller is authenticated. * * @return the paged iterable + * @throws IOException + * Signals that an I/O exception has occurred. */ - public PagedIterable listFollows() { - return listUser("following"); + public PagedIterable listEvents() throws IOException { + return root().createRequest() + .withUrlPath(String.format("/users/%s/events", login)) + .toIterable(GHEventInfo[].class, null); } /** * Lists Gists created by this user. * * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listGists() { + public PagedIterable listGists() throws IOException { return root().createRequest() .withUrlPath(String.format("/users/%s/gists", login)) .toIterable(GHGist[].class, null); } /** - * Lists all the projects. - *

- * https://docs.github.com/en/rest/reference/projects#list-user-projects + * Gets LDAP information for user. * - * @return the paged iterable + * @return The LDAP information + * @throws IOException + * the io exception + * @see Github + * LDAP */ - public PagedIterable listProjects() { - return root().createRequest().withUrlPath(getApiTailUrl("projects")).toIterable(GHProject[].class, null); + public Optional getLdapDn() throws IOException { + super.populate(); + return Optional.ofNullable(ldap_dn); } /** - * Lists all the repositories that this user has starred. + * When was this user suspended?. * - * @return the paged iterable + * @return updated date + * @throws IOException + * on error */ - public PagedIterable listStarredRepositories() { - return listRepositories("starred"); + public Date getSuspendedAt() throws IOException { + super.populate(); + return GitHubClient.parseDate(suspendedAt); } /** - * Lists all the subscribed (aka watched) repositories. - *

- * https://developer.github.com/v3/activity/watching/ + * Hash code. * - * @return the paged iterable + * @return the int */ - public PagedIterable listSubscriptions() { - return listRepositories("subscriptions"); + @Override + public int hashCode() { + return login.hashCode(); } /** - * Unfollow this user. + * Equals. * - * @throws IOException - * the io exception + * @param obj + * the obj + * @return true, if successful */ - public void unfollow() throws IOException { - root().createRequest().method("DELETE").withUrlPath("/user/following/" + login).send(); - } - - private PagedIterable listRepositories(final String suffix) { - return root().createRequest().withUrlPath(getApiTailUrl(suffix)).toIterable(GHRepository[].class, null); - } - - private PagedIterable listUser(final String suffix) { - return root().createRequest().withUrlPath(getApiTailUrl(suffix)).toIterable(GHUser[].class, null); + @Override + public boolean equals(Object obj) { + if (obj instanceof GHUser) { + GHUser that = (GHUser) obj; + return this.login.equals(that.login); + } + return false; } /** diff --git a/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java b/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java index 0193b2139e..8276b3d8e4 100644 --- a/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java @@ -9,28 +9,6 @@ */ public class GHUserSearchBuilder extends GHSearchBuilder { - /** - * The enum Sort. - */ - public enum Sort { - - /** The followers. */ - FOLLOWERS, - /** The joined. */ - JOINED, - /** The repositories. */ - REPOSITORIES - } - - private static class UserSearchResult extends SearchResult { - private GHUser[] items; - - @Override - GHUser[] getItems(GitHub root) { - return items; - } - } - /** * Instantiates a new GH user search builder. * @@ -42,25 +20,26 @@ GHUser[] getItems(GitHub root) { } /** - * Created gh user search builder. + * Search terms. * - * @param v - * the v - * @return the gh user search builder + * @param term + * the term + * @return the GH user search builder */ - public GHUserSearchBuilder created(String v) { - return q("created:" + v); + public GHUserSearchBuilder q(String term) { + super.q(term); + return this; } /** - * Followers gh user search builder. + * Type gh user search builder. * * @param v * the v * @return the gh user search builder */ - public GHUserSearchBuilder followers(String v) { - return q("followers:" + v); + public GHUserSearchBuilder type(String v) { + return q("type:" + v); } /** @@ -75,14 +54,14 @@ public GHUserSearchBuilder in(String v) { } /** - * Language gh user search builder. + * Repos gh user search builder. * * @param v * the v * @return the gh user search builder */ - public GHUserSearchBuilder language(String v) { - return q("language:" + v); + public GHUserSearchBuilder repos(String v) { + return q("repos:" + v); } /** @@ -97,38 +76,48 @@ public GHUserSearchBuilder location(String v) { } /** - * Order gh user search builder. + * Language gh user search builder. * * @param v * the v * @return the gh user search builder */ - public GHUserSearchBuilder order(GHDirection v) { - req.with("order", v); - return this; + public GHUserSearchBuilder language(String v) { + return q("language:" + v); } /** - * Search terms. + * Created gh user search builder. * - * @param term - * the term - * @return the GH user search builder + * @param v + * the v + * @return the gh user search builder */ - public GHUserSearchBuilder q(String term) { - super.q(term); - return this; + public GHUserSearchBuilder created(String v) { + return q("created:" + v); } /** - * Repos gh user search builder. + * Followers gh user search builder. * * @param v * the v * @return the gh user search builder */ - public GHUserSearchBuilder repos(String v) { - return q("repos:" + v); + public GHUserSearchBuilder followers(String v) { + return q("followers:" + v); + } + + /** + * Order gh user search builder. + * + * @param v + * the v + * @return the gh user search builder + */ + public GHUserSearchBuilder order(GHDirection v) { + req.with("order", v); + return this; } /** @@ -144,14 +133,25 @@ public GHUserSearchBuilder sort(Sort sort) { } /** - * Type gh user search builder. - * - * @param v - * the v - * @return the gh user search builder + * The enum Sort. */ - public GHUserSearchBuilder type(String v) { - return q("type:" + v); + public enum Sort { + + /** The followers. */ + FOLLOWERS, + /** The repositories. */ + REPOSITORIES, + /** The joined. */ + JOINED + } + + private static class UserSearchResult extends SearchResult { + private GHUser[] items; + + @Override + GHUser[] getItems(GitHub root) { + return items; + } } /** diff --git a/src/main/java/org/kohsuke/github/GHVerification.java b/src/main/java/org/kohsuke/github/GHVerification.java index 04502b358f..6fb5493e88 100644 --- a/src/main/java/org/kohsuke/github/GHVerification.java +++ b/src/main/java/org/kohsuke/github/GHVerification.java @@ -17,6 +17,53 @@ justification = "JSON API") public class GHVerification { + /** + * Create default GHVerification instance + */ + public GHVerification() { + } + + private String signature, payload; + private boolean verified; + private Reason reason; + + /** + * Indicates whether GitHub considers the signature in this commit to be verified. + * + * @return true if the signature is valid else returns false. + */ + public boolean isVerified() { + return verified; + } + + /** + * Gets reason for verification value. + * + * @return reason of type {@link Reason}, such as "valid" or "unsigned". The possible values can be found in + * {@link Reason}} + */ + public Reason getReason() { + return reason; + } + + /** + * Gets signature used for the verification. + * + * @return null if not signed else encoded signature. + */ + public String getSignature() { + return signature; + } + + /** + * Gets the payload that was signed. + * + * @return null if not signed else encoded signature. + */ + public String getPayload() { + return payload; + } + /** * The possible values for reason in verification object from github. * @@ -26,105 +73,58 @@ public class GHVerification { */ public enum Reason { - /** The signing certificate or its chain could not be verified. */ - BAD_CERT, - - /** Invalid email used for signing. */ - BAD_EMAIL, - /** Signing key expired. */ EXPIRED_KEY, + /** The usage flags for the key that signed this don't allow signing. */ + NOT_SIGNING_KEY, + /** The GPG verification service misbehaved. */ GPGVERIFY_ERROR, /** The GPG verification service is unavailable at the moment. */ GPGVERIFY_UNAVAILABLE, - /** Invalid signature. */ - INVALID, - - /** Malformed signature. (Returned by graphQL) */ - MALFORMED_SIG, - - /** Malformed signature. */ - MALFORMED_SIGNATURE, + /** Unsigned. */ + UNSIGNED, - /** The usage flags for the key that signed this don't allow signing. */ - NOT_SIGNING_KEY, + /** Unknown signature type. */ + UNKNOWN_SIGNATURE_TYPE, /** Email used for signing not known to GitHub. */ NO_USER, - /** Valid signature, though certificate revocation check failed. */ - OCSP_ERROR, - - /** Valid signature, pending certificate revocation checking. */ - OCSP_PENDING, + /** Email used for signing unverified on GitHub. */ + UNVERIFIED_EMAIL, - /** One or more certificates in chain has been revoked. */ - OCSP_REVOKED, + /** Invalid email used for signing. */ + BAD_EMAIL, /** Key used for signing not known to GitHub. */ UNKNOWN_KEY, - /** Unknown signature type. */ - UNKNOWN_SIGNATURE_TYPE, - - /** Unsigned. */ - UNSIGNED, + /** Malformed signature. */ + MALFORMED_SIGNATURE, - /** Email used for signing unverified on GitHub. */ - UNVERIFIED_EMAIL, + /** Invalid signature. */ + INVALID, /** Valid signature and verified by GitHub. */ - VALID - } + VALID, - private Reason reason; - private String signature, payload; - private boolean verified; - - /** - * Create default GHVerification instance - */ - public GHVerification() { - } + /** The signing certificate or its chain could not be verified. */ + BAD_CERT, - /** - * Gets the payload that was signed. - * - * @return null if not signed else encoded signature. - */ - public String getPayload() { - return payload; - } + /** Malformed signature. (Returned by graphQL) */ + MALFORMED_SIG, - /** - * Gets reason for verification value. - * - * @return reason of type {@link Reason}, such as "valid" or "unsigned". The possible values can be found in - * {@link Reason}} - */ - public Reason getReason() { - return reason; - } + /** Valid signature, though certificate revocation check failed. */ + OCSP_ERROR, - /** - * Gets signature used for the verification. - * - * @return null if not signed else encoded signature. - */ - public String getSignature() { - return signature; - } + /** Valid signature, pending certificate revocation checking. */ + OCSP_PENDING, - /** - * Indicates whether GitHub considers the signature in this commit to be verified. - * - * @return true if the signature is valid else returns false. - */ - public boolean isVerified() { - return verified; + /** One or more certificates in chain has been revoked. */ + OCSP_REVOKED } } diff --git a/src/main/java/org/kohsuke/github/GHWorkflow.java b/src/main/java/org/kohsuke/github/GHWorkflow.java index dff9ffdc3d..522870a9cf 100644 --- a/src/main/java/org/kohsuke/github/GHWorkflow.java +++ b/src/main/java/org/kohsuke/github/GHWorkflow.java @@ -19,77 +19,69 @@ */ public class GHWorkflow extends GHObject { - private String badgeUrl; - - private String htmlUrl; + /** + * Create default GHWorkflow instance + */ + public GHWorkflow() { + } - private String name; // Not provided by the API. @JsonIgnore private GHRepository owner; - private String path; + private String name; + private String path; private String state; + + private String htmlUrl; + private String badgeUrl; + /** - * Create default GHWorkflow instance + * The name of the workflow. + * + * @return the name */ - public GHWorkflow() { + public String getName() { + return name; } /** - * Disable the workflow. + * The path of the workflow e.g. .github/workflows/blank.yaml * - * @throws IOException - * the io exception + * @return the path */ - public void disable() throws IOException { - root().createRequest().method("PUT").withUrlPath(getApiRoute(), "disable").send(); + public String getPath() { + return path; } /** - * Create a workflow dispatch event which triggers a manual workflow run. + * The state of the workflow. * - * @param ref - * the git reference for the workflow. The reference can be a branch or tag name. - * @throws IOException - * the io exception + * @return the state */ - public void dispatch(String ref) throws IOException { - dispatch(ref, Collections.emptyMap()); + public String getState() { + return state; } /** - * Create a workflow dispatch event which triggers a manual workflow run. + * Gets the html url. * - * @param ref - * the git reference for the workflow. The reference can be a branch or tag name. - * @param inputs - * input keys and values configured in the workflow file. The maximum number of properties is 10. Any - * default properties configured in the workflow file will be used when inputs are omitted. + * @return the html url * @throws IOException - * the io exception + * Signals that an I/O exception has occurred. */ - public void dispatch(String ref, Map inputs) throws IOException { - Requester requester = root().createRequest() - .method("POST") - .withUrlPath(getApiRoute(), "dispatches") - .with("ref", ref); - - if (!inputs.isEmpty()) { - requester.with("inputs", inputs); - } - - requester.send(); + public URL getHtmlUrl() throws IOException { + return GitHubClient.parseURL(htmlUrl); } /** - * Enable the workflow. + * Repository to which the workflow belongs. * - * @throws IOException - * the io exception + * @return the repository */ - public void enable() throws IOException { - root().createRequest().method("PUT").withUrlPath(getApiRoute(), "enable").send(); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getRepository() { + return owner; } /** @@ -102,49 +94,59 @@ public URL getBadgeUrl() { } /** - * Gets the html url. + * Disable the workflow. * - * @return the html url + * @throws IOException + * the io exception */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public void disable() throws IOException { + root().createRequest().method("PUT").withUrlPath(getApiRoute(), "disable").send(); } /** - * The name of the workflow. + * Enable the workflow. * - * @return the name + * @throws IOException + * the io exception */ - public String getName() { - return name; + public void enable() throws IOException { + root().createRequest().method("PUT").withUrlPath(getApiRoute(), "enable").send(); } /** - * The path of the workflow e.g. .github/workflows/blank.yaml + * Create a workflow dispatch event which triggers a manual workflow run. * - * @return the path + * @param ref + * the git reference for the workflow. The reference can be a branch or tag name. + * @throws IOException + * the io exception */ - public String getPath() { - return path; + public void dispatch(String ref) throws IOException { + dispatch(ref, Collections.emptyMap()); } /** - * Repository to which the workflow belongs. + * Create a workflow dispatch event which triggers a manual workflow run. * - * @return the repository + * @param ref + * the git reference for the workflow. The reference can be a branch or tag name. + * @param inputs + * input keys and values configured in the workflow file. The maximum number of properties is 10. Any + * default properties configured in the workflow file will be used when inputs are omitted. + * @throws IOException + * the io exception */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getRepository() { - return owner; - } + public void dispatch(String ref, Map inputs) throws IOException { + Requester requester = root().createRequest() + .method("POST") + .withUrlPath(getApiRoute(), "dispatches") + .with("ref", ref); - /** - * The state of the workflow. - * - * @return the state - */ - public String getState() { - return state; + if (!inputs.isEmpty()) { + requester.with("inputs", inputs); + } + + requester.send(); } /** diff --git a/src/main/java/org/kohsuke/github/GHWorkflowJob.java b/src/main/java/org/kohsuke/github/GHWorkflowJob.java index c4fddcb553..76a2fddaef 100644 --- a/src/main/java/org/kohsuke/github/GHWorkflowJob.java +++ b/src/main/java/org/kohsuke/github/GHWorkflowJob.java @@ -1,7 +1,6 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import org.kohsuke.github.GHWorkflowRun.Conclusion; @@ -10,7 +9,6 @@ import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -28,147 +26,65 @@ public class GHWorkflowJob extends GHObject { /** - * The Class Step. + * Create default GHWorkflowJob instance */ - public static class Step extends GitHubBridgeAdapterObject { - - private String completedAt; - - private String conclusion; - private String name; - - private int number; - private String startedAt; - - private String status; - /** - * Create default Step instance - */ - public Step() { - } - - /** - * When was this step completed?. - * - * @return completion date - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCompletedAt() { - return GitHubClient.parseInstant(completedAt); - } - - /** - * Gets the conclusion of the step. - *

- * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. - * - * @return conclusion of the step - */ - public Conclusion getConclusion() { - return Conclusion.from(conclusion); - } - - /** - * Gets the name of the step. - * - * @return name - */ - public String getName() { - return name; - } - - /** - * Gets the sequential number of the step. - * - * @return number - */ - public int getNumber() { - return number; - } + public GHWorkflowJob() { + } - /** - * When was this step started?. - * - * @return start date - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getStartedAt() { - return GitHubClient.parseInstant(startedAt); - } + // Not provided by the API. + @JsonIgnore + private GHRepository owner; - /** - * Gets status of the step. - *

- * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. - * - * @return status of the step - */ - public Status getStatus() { - return Status.from(status); - } - } + private String name; - private String checkRunUrl; + private String headSha; + private String startedAt; private String completedAt; + private String status; private String conclusion; - private String headSha; - private String htmlUrl; - - private List labels = new ArrayList<>(); - private String name; - - // Not provided by the API. - @JsonIgnore - private GHRepository owner; + private long runId; private int runAttempt; - private long runId; - private int runnerGroupId; + private String htmlUrl; + private String checkRunUrl; - private String runnerGroupName; private int runnerId; private String runnerName; - private String startedAt; - - private String status; + private int runnerGroupId; + private String runnerGroupName; private List steps = new ArrayList<>(); + private List labels = new ArrayList<>(); + /** - * Create default GHWorkflowJob instance + * The name of the job. + * + * @return the name */ - public GHWorkflowJob() { + public String getName() { + return name; } /** - * Downloads the logs. - *

- * The logs are returned as a text file. + * Gets the HEAD SHA. * - * @param - * the type of result - * @param streamFunction - * The {@link InputStreamFunction} that will process the stream - * @return the result of reading the stream. - * @throws IOException - * The IO exception. + * @return sha for the HEAD commit */ - public T downloadLogs(InputStreamFunction streamFunction) throws IOException { - requireNonNull(streamFunction, "Stream function must not be null"); - - return root().createRequest().method("GET").withUrlPath(getApiRoute(), "logs").fetchStream(streamFunction); + public String getHeadSha() { + return headSha; } /** - * The check run URL. + * When was this job started?. * - * @return the check run url + * @return start date */ - public URL getCheckRunUrl() { - return GitHubClient.parseURL(checkRunUrl); + public Date getStartedAt() { + return GitHubClient.parseDate(startedAt); } /** @@ -176,9 +92,19 @@ public URL getCheckRunUrl() { * * @return completion date */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCompletedAt() { - return GitHubClient.parseInstant(completedAt); + public Date getCompletedAt() { + return GitHubClient.parseDate(completedAt); + } + + /** + * Gets status of the job. + *

+ * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. + * + * @return status of the job + */ + public Status getStatus() { + return Status.from(status); } /** @@ -193,12 +119,21 @@ public Conclusion getConclusion() { } /** - * Gets the HEAD SHA. + * The run id. * - * @return sha for the HEAD commit + * @return the run id */ - public String getHeadSha() { - return headSha; + public long getRunId() { + return runId; + } + + /** + * Attempt number of the associated workflow run, 1 for first attempt and higher if the workflow was re-run. + * + * @return attempt number + */ + public int getRunAttempt() { + return runAttempt; } /** @@ -211,49 +146,48 @@ public URL getHtmlUrl() { } /** - * Gets the labels of the job. + * The check run URL. * - * @return the labels + * @return the check run url */ - public List getLabels() { - return Collections.unmodifiableList(labels); + public URL getCheckRunUrl() { + return GitHubClient.parseURL(checkRunUrl); } /** - * The name of the job. + * Gets the execution steps of this job. * - * @return the name + * @return the execution steps */ - public String getName() { - return name; + public List getSteps() { + return Collections.unmodifiableList(steps); } /** - * Repository to which the job belongs. + * Gets the labels of the job. * - * @return the repository + * @return the labels */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getRepository() { - return owner; + public List getLabels() { + return Collections.unmodifiableList(labels); } /** - * Attempt number of the associated workflow run, 1 for first attempt and higher if the workflow was re-run. + * the runner id. * - * @return attempt number + * @return runnerId */ - public int getRunAttempt() { - return runAttempt; + public int getRunnerId() { + return runnerId; } /** - * The run id. + * the runner name. * - * @return the run id + * @return runnerName */ - public long getRunId() { - return runId; + public String getRunnerName() { + return runnerName; } /** @@ -275,51 +209,32 @@ public String getRunnerGroupName() { } /** - * the runner id. - * - * @return runnerId - */ - public int getRunnerId() { - return runnerId; - } - - /** - * the runner name. - * - * @return runnerName - */ - public String getRunnerName() { - return runnerName; - } - - /** - * When was this job started?. + * Repository to which the job belongs. * - * @return start date + * @return the repository */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getStartedAt() { - return GitHubClient.parseInstant(startedAt); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getRepository() { + return owner; } /** - * Gets status of the job. + * Downloads the logs. *

- * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. + * The logs are returned as a text file. * - * @return status of the job + * @param + * the type of result + * @param streamFunction + * The {@link InputStreamFunction} that will process the stream + * @return the result of reading the stream. + * @throws IOException + * The IO exception. */ - public Status getStatus() { - return Status.from(status); - } + public T downloadLogs(InputStreamFunction streamFunction) throws IOException { + requireNonNull(streamFunction, "Stream function must not be null"); - /** - * Gets the execution steps of this job. - * - * @return the execution steps - */ - public List getSteps() { - return Collections.unmodifiableList(steps); + return root().createRequest().method("GET").withUrlPath(getApiRoute(), "logs").fetchStream(streamFunction); } private String getApiRoute() { @@ -343,4 +258,83 @@ GHWorkflowJob wrapUp(GHRepository owner) { this.owner = owner; return this; } + + /** + * The Class Step. + */ + public static class Step { + + /** + * Create default Step instance + */ + public Step() { + } + + private String name; + private int number; + + private String startedAt; + private String completedAt; + + private String status; + private String conclusion; + + /** + * Gets the name of the step. + * + * @return name + */ + public String getName() { + return name; + } + + /** + * Gets the sequential number of the step. + * + * @return number + */ + public int getNumber() { + return number; + } + + /** + * When was this step started?. + * + * @return start date + */ + public Date getStartedAt() { + return GitHubClient.parseDate(startedAt); + } + + /** + * When was this step completed?. + * + * @return completion date + */ + public Date getCompletedAt() { + return GitHubClient.parseDate(completedAt); + } + + /** + * Gets status of the step. + *

+ * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. + * + * @return status of the step + */ + public Status getStatus() { + return Status.from(status); + } + + /** + * Gets the conclusion of the step. + *

+ * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. + * + * @return conclusion of the step + */ + public Conclusion getConclusion() { + return Conclusion.from(conclusion); + } + } } diff --git a/src/main/java/org/kohsuke/github/GHWorkflowJobQueryBuilder.java b/src/main/java/org/kohsuke/github/GHWorkflowJobQueryBuilder.java index 9f011e9612..f9ff3a1e3e 100644 --- a/src/main/java/org/kohsuke/github/GHWorkflowJobQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHWorkflowJobQueryBuilder.java @@ -22,22 +22,22 @@ public class GHWorkflowJobQueryBuilder extends GHQueryBuilder { } /** - * Apply a filter to return jobs from all executions of this workflow run. + * Apply a filter to only return the jobs of the most recent execution of the workflow run. * - * @return the workflow run job run query builder + * @return the workflow run job query builder */ - public GHWorkflowJobQueryBuilder all() { - req.with("filter", "all"); + public GHWorkflowJobQueryBuilder latest() { + req.with("filter", "latest"); return this; } /** - * Apply a filter to only return the jobs of the most recent execution of the workflow run. + * Apply a filter to return jobs from all executions of this workflow run. * - * @return the workflow run job query builder + * @return the workflow run job run query builder */ - public GHWorkflowJobQueryBuilder latest() { - req.with("filter", "latest"); + public GHWorkflowJobQueryBuilder all() { + req.with("filter", "all"); return this; } diff --git a/src/main/java/org/kohsuke/github/GHWorkflowJobsPage.java b/src/main/java/org/kohsuke/github/GHWorkflowJobsPage.java index 8d4a7ca772..91d7013f70 100644 --- a/src/main/java/org/kohsuke/github/GHWorkflowJobsPage.java +++ b/src/main/java/org/kohsuke/github/GHWorkflowJobsPage.java @@ -9,8 +9,8 @@ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") class GHWorkflowJobsPage { + private int total_count; private GHWorkflowJob[] jobs; - private int totalCount; /** * Gets the total count. @@ -18,7 +18,7 @@ class GHWorkflowJobsPage { * @return the total count */ public int getTotalCount() { - return totalCount; + return total_count; } /** diff --git a/src/main/java/org/kohsuke/github/GHWorkflowRun.java b/src/main/java/org/kohsuke/github/GHWorkflowRun.java index 7e25b29b5f..6077e4480c 100644 --- a/src/main/java/org/kohsuke/github/GHWorkflowRun.java +++ b/src/main/java/org/kohsuke/github/GHWorkflowRun.java @@ -1,7 +1,6 @@ package org.kohsuke.github; import com.fasterxml.jackson.annotation.JsonProperty; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang3.StringUtils; import org.kohsuke.github.function.InputStreamFunction; @@ -9,7 +8,6 @@ import java.io.IOException; import java.net.URL; -import java.time.Instant; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -29,300 +27,125 @@ public class GHWorkflowRun extends GHObject { /** - * The Enum Conclusion. - */ - public static enum Conclusion { - - /** The action required. */ - ACTION_REQUIRED, - /** The cancelled. */ - CANCELLED, - /** The failure. */ - FAILURE, - /** The neutral. */ - NEUTRAL, - /** The skipped. */ - SKIPPED, - /** The stale. */ - STALE, - /** Start up fail */ - STARTUP_FAILURE, - /** The success. */ - SUCCESS, - /** The timed out. */ - TIMED_OUT, - /** The unknown. */ - UNKNOWN; - - /** - * From. - * - * @param value - * the value - * @return the conclusion - */ - public static Conclusion from(String value) { - return EnumUtils.getNullableEnumOrDefault(Conclusion.class, value, Conclusion.UNKNOWN); - } - - /** - * To string. - * - * @return the string - */ - @Override - public String toString() { - return name().toLowerCase(Locale.ROOT); - } - } - - /** - * The Class HeadCommit. + * Create default GHWorkflowRun instance */ - public static class HeadCommit extends GitHubBridgeAdapterObject { - - private GitUser author; - - private GitUser committer; - private String id; - private String message; - private String timestamp; - private String treeId; - /** - * Create default HeadCommit instance - */ - public HeadCommit() { - } - - /** - * Gets author. - * - * @return the author - */ - public GitUser getAuthor() { - return author; - } - - /** - * Gets committer. - * - * @return the committer - */ - public GitUser getCommitter() { - return committer; - } - - /** - * Gets id of the commit. - * - * @return id of the commit - */ - public String getId() { - return id; - } - - /** - * Gets message. - * - * @return commit message. - */ - public String getMessage() { - return message; - } - - /** - * Gets timestamp of the commit. - * - * @return timestamp of the commit - */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getTimestamp() { - return GitHubClient.parseInstant(timestamp); - } - - /** - * Gets id of the tree. - * - * @return id of the tree - */ - public String getTreeId() { - return treeId; - } + public GHWorkflowRun() { } - /** - * The Enum Status. - */ - public static enum Status { + @JsonProperty("repository") + private GHRepository owner; - /** The action required. */ - ACTION_REQUIRED, - /** The cancelled. */ - CANCELLED, - /** The completed. */ - COMPLETED, - /** The failure. */ - FAILURE, - /** The in progress. */ - IN_PROGRESS, - /** The neutral. */ - NEUTRAL, - /** The pending. */ - PENDING, - /** The queued. */ - QUEUED, - /** The requested. */ - REQUESTED, - /** The skipped. */ - SKIPPED, - /** The stale. */ - STALE, - /** The success. */ - SUCCESS, - /** The timed out. */ - TIMED_OUT, - /** The unknown. */ - UNKNOWN, - /** The waiting. */ - WAITING; + private String name; + private String displayTitle; + private long runNumber; + private long workflowId; - /** - * From. - * - * @param value - * the value - * @return the status - */ - public static Status from(String value) { - return EnumUtils.getNullableEnumOrDefault(Status.class, value, Status.UNKNOWN); - } + private long runAttempt; + private String runStartedAt; - /** - * To string. - * - * @return the string - */ - @Override - public String toString() { - return name().toLowerCase(Locale.ROOT); - } - } + private String htmlUrl; + private String jobsUrl; + private String logsUrl; + private String checkSuiteUrl; private String artifactsUrl; private String cancelUrl; - private String checkSuiteUrl; - - private String conclusion; - private String displayTitle; - private String event; + private String rerunUrl; + private String workflowUrl; private String headBranch; - private HeadCommit headCommit; - private GHRepository headRepository; private String headSha; - private String htmlUrl; - private String jobsUrl; - private String logsUrl; - private String name; - - @JsonProperty("repository") - private GHRepository owner; - private GHPullRequest[] pullRequests; - private String rerunUrl; - private long runAttempt; + private GHRepository headRepository; + private HeadCommit headCommit; - private long runNumber; - private String runStartedAt; + private String event; private String status; + private String conclusion; - private GHUser triggeringActor; - - private long workflowId; + private GHPullRequest[] pullRequests; - private String workflowUrl; + /** + * The name of the workflow run. + * + * @return the name + */ + public String getName() { + return name; + } /** - * Create default GHWorkflowRun instance + * The display title of the workflow run. + * + * @return the displayTitle */ - public GHWorkflowRun() { + public String getDisplayTitle() { + return displayTitle; } /** - * Approve the workflow run. + * The run number. * - * @throws IOException - * the io exception + * @return the run number */ - public void approve() throws IOException { - root().createRequest().method("POST").withUrlPath(getApiRoute(), "approve").send(); + public long getRunNumber() { + return runNumber; } /** - * Cancel the workflow run. + * The workflow id. * - * @throws IOException - * the io exception + * @return the workflow id */ - public void cancel() throws IOException { - root().createRequest().method("POST").withUrlPath(getApiRoute(), "cancel").send(); + public long getWorkflowId() { + return workflowId; } /** - * Delete the workflow run. + * The run attempt. * - * @throws IOException - * the io exception + * @return the run attempt */ - public void delete() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); + public long getRunAttempt() { + return runAttempt; } /** - * Delete the logs. + * When was this run triggered?. * + * @return run triggered * @throws IOException - * the io exception + * on error */ - public void deleteLogs() throws IOException { - root().createRequest().method("DELETE").withUrlPath(getApiRoute(), "logs").send(); + public Date getRunStartedAt() throws IOException { + return GitHubClient.parseDate(runStartedAt); } /** - * Downloads the logs. - *

- * The logs are in the form of a zip archive. - *

- * Note that the archive is the same as the one downloaded from a workflow run so it contains the logs for all jobs. + * Gets the html url. * - * @param - * the type of result - * @param streamFunction - * The {@link InputStreamFunction} that will process the stream - * @return the result of reading the stream. + * @return the html url * @throws IOException - * The IO exception. + * Signals that an I/O exception has occurred. */ - public T downloadLogs(InputStreamFunction streamFunction) throws IOException { - requireNonNull(streamFunction, "Stream function must not be null"); - - return root().createRequest().method("GET").withUrlPath(getApiRoute(), "logs").fetchStream(streamFunction); + public URL getHtmlUrl() throws IOException { + return GitHubClient.parseURL(htmlUrl); } /** - * The artifacts URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts + * The jobs URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs * - * @return the artifacts url + * @return the jobs url */ - public URL getArtifactsUrl() { - return GitHubClient.parseURL(artifactsUrl); + public URL getJobsUrl() { + return GitHubClient.parseURL(jobsUrl); } /** - * The cancel URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel + * The logs URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs * - * @return the cancel url + * @return the logs url */ - public URL getCancelUrl() { - return GitHubClient.parseURL(cancelUrl); + public URL getLogsUrl() { + return GitHubClient.parseURL(logsUrl); } /** @@ -335,32 +158,39 @@ public URL getCheckSuiteUrl() { } /** - * Gets the conclusion of the workflow run. - *

- * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. + * The artifacts URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts * - * @return conclusion of the workflow run + * @return the artifacts url */ - public Conclusion getConclusion() { - return Conclusion.from(conclusion); + public URL getArtifactsUrl() { + return GitHubClient.parseURL(artifactsUrl); } /** - * The display title of the workflow run. + * The cancel URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel * - * @return the displayTitle + * @return the cancel url */ - public String getDisplayTitle() { - return displayTitle; + public URL getCancelUrl() { + return GitHubClient.parseURL(cancelUrl); } /** - * The type of event that triggered the build. + * The rerun URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun * - * @return type of event + * @return the rerun url */ - public GHEvent getEvent() { - return EnumUtils.getNullableEnumOrDefault(GHEvent.class, event, GHEvent.UNKNOWN); + public URL getRerunUrl() { + return GitHubClient.parseURL(rerunUrl); + } + + /** + * The workflow URL, like https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038 + * + * @return the workflow url + */ + public URL getWorkflowUrl() { + return GitHubClient.parseURL(workflowUrl); } /** @@ -372,6 +202,15 @@ public String getHeadBranch() { return headBranch; } + /** + * Gets the HEAD SHA. + * + * @return sha for the HEAD commit + */ + public String getHeadSha() { + return headSha; + } + /** * The commit of current head. * @@ -392,48 +231,44 @@ public GHRepository getHeadRepository() { } /** - * Gets the HEAD SHA. - * - * @return sha for the HEAD commit - */ - public String getHeadSha() { - return headSha; - } - - /** - * Gets the html url. + * The type of event that triggered the build. * - * @return the html url + * @return type of event */ - public URL getHtmlUrl() { - return GitHubClient.parseURL(htmlUrl); + public GHEvent getEvent() { + return EnumUtils.getNullableEnumOrDefault(GHEvent.class, event, GHEvent.UNKNOWN); } /** - * The jobs URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs + * Gets status of the workflow run. + *

+ * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. * - * @return the jobs url + * @return status of the workflow run */ - public URL getJobsUrl() { - return GitHubClient.parseURL(jobsUrl); + public Status getStatus() { + return Status.from(status); } /** - * The logs URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs + * Gets the conclusion of the workflow run. + *

+ * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. * - * @return the logs url + * @return conclusion of the workflow run */ - public URL getLogsUrl() { - return GitHubClient.parseURL(logsUrl); + public Conclusion getConclusion() { + return Conclusion.from(conclusion); } /** - * The name of the workflow run. + * Repository to which the workflow run belongs. * - * @return the name + * @return the repository */ - public String getName() { - return name; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getRepository() { + return owner; } /** @@ -453,112 +288,88 @@ public List getPullRequests() throws IOException { pullRequest.refresh(pullRequest.getTitle()); } return Collections.unmodifiableList(Arrays.asList(pullRequests)); - } - return Collections.emptyList(); - } - - /** - * Repository to which the workflow run belongs. - * - * @return the repository - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getRepository() { - return owner; - } - - /** - * The rerun URL, like https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun - * - * @return the rerun url - */ - public URL getRerunUrl() { - return GitHubClient.parseURL(rerunUrl); - } - - /** - * The run attempt. - * - * @return the run attempt - */ - public long getRunAttempt() { - return runAttempt; - } - - /** - * The run number. - * - * @return the run number - */ - public long getRunNumber() { - return runNumber; + } + return Collections.emptyList(); } /** - * When was this run triggered?. + * Cancel the workflow run. * - * @return run triggered + * @throws IOException + * the io exception */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getRunStartedAt() { - return GitHubClient.parseInstant(runStartedAt); + public void cancel() throws IOException { + root().createRequest().method("POST").withUrlPath(getApiRoute(), "cancel").send(); } /** - * Gets status of the workflow run. - *

- * Can be {@code UNKNOWN} if the value returned by GitHub is unknown from the API. + * Delete the workflow run. * - * @return status of the workflow run + * @throws IOException + * the io exception */ - public Status getStatus() { - return Status.from(status); + public void delete() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute()).send(); } /** - * The actor which triggered the run. + * Rerun the workflow run. * - * @return the triggering actor + * @throws IOException + * the io exception */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHUser getTriggeringActor() { - return triggeringActor; + public void rerun() throws IOException { + root().createRequest().method("POST").withUrlPath(getApiRoute(), "rerun").send(); } /** - * The workflow id. + * Approve the workflow run. * - * @return the workflow id + * @throws IOException + * the io exception */ - public long getWorkflowId() { - return workflowId; + public void approve() throws IOException { + root().createRequest().method("POST").withUrlPath(getApiRoute(), "approve").send(); } /** - * The workflow URL, like https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038 + * Lists the artifacts attached to this workflow run. * - * @return the workflow url + * @return the paged iterable */ - public URL getWorkflowUrl() { - return GitHubClient.parseURL(workflowUrl); + public PagedIterable listArtifacts() { + return new GHArtifactsIterable(owner, root().createRequest().withUrlPath(getApiRoute(), "artifacts")); } /** - * Returns the list of jobs from all the executions of this workflow run. + * Downloads the logs. + *

+ * The logs are in the form of a zip archive. + *

+ * Note that the archive is the same as the one downloaded from a workflow run so it contains the logs for all jobs. * - * @return list of jobs from all the executions + * @param + * the type of result + * @param streamFunction + * The {@link InputStreamFunction} that will process the stream + * @return the result of reading the stream. + * @throws IOException + * The IO exception. */ - public PagedIterable listAllJobs() { - return new GHWorkflowJobQueryBuilder(this).all().list(); + public T downloadLogs(InputStreamFunction streamFunction) throws IOException { + requireNonNull(streamFunction, "Stream function must not be null"); + + return root().createRequest().method("GET").withUrlPath(getApiRoute(), "logs").fetchStream(streamFunction); } /** - * Lists the artifacts attached to this workflow run. + * Delete the logs. * - * @return the paged iterable + * @throws IOException + * the io exception */ - public PagedIterable listArtifacts() { - return new GHArtifactsIterable(owner, root().createRequest().withUrlPath(getApiRoute(), "artifacts")); + public void deleteLogs() throws IOException { + root().createRequest().method("DELETE").withUrlPath(getApiRoute(), "logs").send(); } /** @@ -571,13 +382,12 @@ public PagedIterable listJobs() { } /** - * Rerun the workflow run. + * Returns the list of jobs from all the executions of this workflow run. * - * @throws IOException - * the io exception + * @return list of jobs from all the executions */ - public void rerun() throws IOException { - root().createRequest().method("POST").withUrlPath(getApiRoute(), "rerun").send(); + public PagedIterable listAllJobs() { + return new GHWorkflowJobQueryBuilder(this).all().list(); } private String getApiRoute() { @@ -619,4 +429,183 @@ GHWorkflowRun wrapUp(GitHub root) { } return this; } + + /** + * The Class HeadCommit. + */ + public static class HeadCommit { + + /** + * Create default HeadCommit instance + */ + public HeadCommit() { + } + + private String id; + private String treeId; + private String message; + private String timestamp; + private GitUser author; + private GitUser committer; + + /** + * Gets id of the commit. + * + * @return id of the commit + */ + public String getId() { + return id; + } + + /** + * Gets id of the tree. + * + * @return id of the tree + */ + public String getTreeId() { + return treeId; + } + + /** + * Gets message. + * + * @return commit message. + */ + public String getMessage() { + return message; + } + + /** + * Gets timestamp of the commit. + * + * @return timestamp of the commit + */ + public Date getTimestamp() { + return GitHubClient.parseDate(timestamp); + } + + /** + * Gets author. + * + * @return the author + */ + public GitUser getAuthor() { + return author; + } + + /** + * Gets committer. + * + * @return the committer + */ + public GitUser getCommitter() { + return committer; + } + } + + /** + * The Enum Status. + */ + public static enum Status { + + /** The queued. */ + QUEUED, + /** The in progress. */ + IN_PROGRESS, + /** The completed. */ + COMPLETED, + /** The action required. */ + ACTION_REQUIRED, + /** The cancelled. */ + CANCELLED, + /** The failure. */ + FAILURE, + /** The neutral. */ + NEUTRAL, + /** The skipped. */ + SKIPPED, + /** The stale. */ + STALE, + /** The success. */ + SUCCESS, + /** The timed out. */ + TIMED_OUT, + /** The requested. */ + REQUESTED, + /** The waiting. */ + WAITING, + /** The pending. */ + PENDING, + /** The unknown. */ + UNKNOWN; + + /** + * From. + * + * @param value + * the value + * @return the status + */ + public static Status from(String value) { + return EnumUtils.getNullableEnumOrDefault(Status.class, value, Status.UNKNOWN); + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + return name().toLowerCase(Locale.ROOT); + } + } + + /** + * The Enum Conclusion. + */ + public static enum Conclusion { + + /** The action required. */ + ACTION_REQUIRED, + /** The cancelled. */ + CANCELLED, + /** The failure. */ + FAILURE, + /** The neutral. */ + NEUTRAL, + /** The success. */ + SUCCESS, + /** The skipped. */ + SKIPPED, + /** The stale. */ + STALE, + /** The timed out. */ + TIMED_OUT, + /** Start up fail */ + STARTUP_FAILURE, + /** The unknown. */ + UNKNOWN; + + /** + * From. + * + * @param value + * the value + * @return the conclusion + */ + public static Conclusion from(String value) { + return EnumUtils.getNullableEnumOrDefault(Conclusion.class, value, Conclusion.UNKNOWN); + } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() { + return name().toLowerCase(Locale.ROOT); + } + } } diff --git a/src/main/java/org/kohsuke/github/GHWorkflowRunQueryBuilder.java b/src/main/java/org/kohsuke/github/GHWorkflowRunQueryBuilder.java index 105dd77a84..b5575abcdc 100644 --- a/src/main/java/org/kohsuke/github/GHWorkflowRunQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHWorkflowRunQueryBuilder.java @@ -31,8 +31,8 @@ public class GHWorkflowRunQueryBuilder extends GHQueryBuilder { * the actor * @return the gh workflow run query builder */ - public GHWorkflowRunQueryBuilder actor(GHUser actor) { - req.with("actor", actor.getLogin()); + public GHWorkflowRunQueryBuilder actor(String actor) { + req.with("actor", actor); return this; } @@ -43,8 +43,8 @@ public GHWorkflowRunQueryBuilder actor(GHUser actor) { * the actor * @return the gh workflow run query builder */ - public GHWorkflowRunQueryBuilder actor(String actor) { - req.with("actor", actor); + public GHWorkflowRunQueryBuilder actor(GHUser actor) { + req.with("actor", actor.getLogin()); return this; } @@ -60,6 +60,42 @@ public GHWorkflowRunQueryBuilder branch(String branch) { return this; } + /** + * Event workflow run query builder. + * + * @param event + * the event + * @return the gh workflow run query builder + */ + public GHWorkflowRunQueryBuilder event(GHEvent event) { + req.with("event", event.symbol()); + return this; + } + + /** + * Event workflow run query builder. + * + * @param event + * the event + * @return the gh workflow run query builder + */ + public GHWorkflowRunQueryBuilder event(String event) { + req.with("event", event); + return this; + } + + /** + * Status workflow run query builder. + * + * @param status + * the status + * @return the gh workflow run query builder + */ + public GHWorkflowRunQueryBuilder status(Status status) { + req.with("status", status.toString()); + return this; + } + /** * Conclusion workflow run query builder. *

@@ -90,30 +126,6 @@ public GHWorkflowRunQueryBuilder created(String created) { return this; } - /** - * Event workflow run query builder. - * - * @param event - * the event - * @return the gh workflow run query builder - */ - public GHWorkflowRunQueryBuilder event(GHEvent event) { - req.with("event", event.symbol()); - return this; - } - - /** - * Event workflow run query builder. - * - * @param event - * the event - * @return the gh workflow run query builder - */ - public GHWorkflowRunQueryBuilder event(String event) { - req.with("event", event); - return this; - } - /** * Head sha workflow run query builder. * @@ -135,16 +147,4 @@ public GHWorkflowRunQueryBuilder headSha(String headSha) { public PagedIterable list() { return new GHWorkflowRunsIterable(repo, req.withUrlPath(repo.getApiTailUrl("actions/runs"))); } - - /** - * Status workflow run query builder. - * - * @param status - * the status - * @return the gh workflow run query builder - */ - public GHWorkflowRunQueryBuilder status(Status status) { - req.with("status", status.toString()); - return this; - } } diff --git a/src/main/java/org/kohsuke/github/GHWorkflowsPage.java b/src/main/java/org/kohsuke/github/GHWorkflowsPage.java index 1fb87a8147..7786d11fab 100644 --- a/src/main/java/org/kohsuke/github/GHWorkflowsPage.java +++ b/src/main/java/org/kohsuke/github/GHWorkflowsPage.java @@ -9,7 +9,7 @@ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") class GHWorkflowsPage { - private int totalCount; + private int total_count; private GHWorkflow[] workflows; /** @@ -18,7 +18,7 @@ class GHWorkflowsPage { * @return the total count */ public int getTotalCount() { - return totalCount; + return total_count; } /** diff --git a/src/main/java/org/kohsuke/github/GitCommit.java b/src/main/java/org/kohsuke/github/GitCommit.java index cc6619b33f..4478edf7cc 100644 --- a/src/main/java/org/kohsuke/github/GitCommit.java +++ b/src/main/java/org/kohsuke/github/GitCommit.java @@ -1,9 +1,7 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.time.Instant; import java.util.AbstractList; import java.util.Collections; import java.util.Date; @@ -18,26 +16,26 @@ */ @SuppressFBWarnings(value = { "NP_UNWRITTEN_FIELD", "UWF_UNWRITTEN_FIELD" }, justification = "JSON API") -public class GitCommit extends GitHubBridgeAdapterObject { +public class GitCommit { + private GHRepository owner; + private String sha, node_id, url, html_url; + private GitUser author; + private GitUser committer; + + private String message; + + private GHVerification verification; + /** * The Class Tree. */ static class Tree { - /** The sha. */ - String sha; - /** The url. */ String url; - /** - * Gets the sha. - * - * @return the sha - */ - public String getSha() { - return sha; - } + /** The sha. */ + String sha; /** * Gets the url. @@ -48,20 +46,20 @@ public String getUrl() { return url; } - } - private GitUser author; - private GitUser committer; - private String message; - - private GHRepository owner; - - private List parents; + /** + * Gets the sha. + * + * @return the sha + */ + public String getSha() { + return sha; + } - private String sha, nodeId, url, htmlUrl; + } private Tree tree; - private GHVerification verification; + private List parents; /** * Instantiates a new git commit. @@ -81,9 +79,9 @@ public GitCommit() { // to GHCommit, for testing purposes this.owner = commit.getOwner(); this.sha = commit.getSha(); - this.nodeId = commit.getNodeId(); + this.node_id = commit.getNodeId(); this.url = commit.getUrl(); - this.htmlUrl = commit.getHtmlUrl(); + this.html_url = commit.getHtmlUrl(); this.author = commit.getAuthor(); this.committer = commit.getCommitter(); this.message = commit.getMessage(); @@ -93,41 +91,49 @@ public GitCommit() { } /** - * Gets author. + * Gets owner. * - * @return the author + * @return the repository that contains the commit. */ - public GitUser getAuthor() { - return author; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") + public GHRepository getOwner() { + return owner; } /** - * Gets authored date. + * Gets SHA1. * - * @return the authored date + * @return The SHA1 of this commit */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getAuthoredDate() { - return author.getDate(); + public String getSHA1() { + return sha; } /** - * Gets commit date. + * Gets SHA. * - * @return the commit date + * @return The SHA of this commit */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getCommitDate() { - return committer.getDate(); + public String getSha() { + return sha; } /** - * Gets committer. + * Gets node id. * - * @return the committer + * @return The node id of this commit */ - public GitUser getCommitter() { - return committer; + public String getNodeId() { + return node_id; + } + + /** + * Gets URL. + * + * @return The URL of this commit + */ + public String getUrl() { + return url; } /** @@ -136,74 +142,70 @@ public GitUser getCommitter() { * @return The HTML URL of this commit */ public String getHtmlUrl() { - return htmlUrl; + return html_url; } /** - * Gets message. + * Gets author. * - * @return Commit message. + * @return the author */ - public String getMessage() { - return message; + public GitUser getAuthor() { + return author; } /** - * Gets node id. + * Gets authored date. * - * @return The node id of this commit + * @return the authored date */ - public String getNodeId() { - return nodeId; + public Date getAuthoredDate() { + return author.getDate(); } /** - * Gets owner. + * Gets committer. * - * @return the repository that contains the commit. + * @return the committer */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected behavior") - public GHRepository getOwner() { - return owner; + public GitUser getCommitter() { + return committer; } /** - * Gets the parent SHA 1 s. + * Gets commit date. * - * @return the parent SHA 1 s + * @return the commit date */ - public List getParentSHA1s() { - if (parents == null || parents.size() == 0) - return Collections.emptyList(); - return new AbstractList() { - @Override - public String get(int index) { - return parents.get(index).sha; - } + public Date getCommitDate() { + return committer.getDate(); + } - @Override - public int size() { - return parents.size(); - } - }; + /** + * Gets message. + * + * @return Commit message. + */ + public String getMessage() { + return message; } /** - * Gets SHA1. + * Gets Verification Status. * - * @return The SHA1 of this commit + * @return the Verification status */ - public String getSHA1() { - return sha; + public GHVerification getVerification() { + return verification; } /** - * Gets SHA. + * Gets the tree. * - * @return The SHA of this commit + * @return the tree */ - public String getSha() { - return sha; + Tree getTree() { + return tree; } /** @@ -224,24 +226,6 @@ public String getTreeUrl() { return tree.getUrl(); } - /** - * Gets URL. - * - * @return The URL of this commit - */ - public String getUrl() { - return url; - } - - /** - * Gets Verification Status. - * - * @return the Verification status - */ - public GHVerification getVerification() { - return verification; - } - /** * Gets the parents. * @@ -253,21 +237,24 @@ List getParents() { } /** - * Gets the tree. + * Gets the parent SHA 1 s. * - * @return the tree + * @return the parent SHA 1 s */ - Tree getTree() { - return tree; - } + public List getParentSHA1s() { + if (parents == null || parents.size() == 0) + return Collections.emptyList(); + return new AbstractList() { + @Override + public String get(int index) { + return parents.get(index).sha; + } - /** - * For test purposes only. - * - * @return Equivalent GHCommit - */ - GHCommit toGHCommit() { - return new GHCommit(new GHCommit.ShortInfo(this)); + @Override + public int size() { + return parents.size(); + } + }; } /** @@ -282,4 +269,13 @@ GitCommit wrapUp(GHRepository owner) { return this; } + /** + * For test purposes only. + * + * @return Equivalent GHCommit + */ + GHCommit toGHCommit() { + return new GHCommit(new GHCommit.ShortInfo(this)); + } + } diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index cb47de47af..aa5b6239e3 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -55,14 +55,145 @@ */ public class GitHub { + @Nonnull + private final GitHubClient client; + + @CheckForNull + private GHMyself myself; + + private final ConcurrentMap users; + private final ConcurrentMap orgs; + + @Nonnull + private final GitHubSanityCachedValue sanityCachedMeta = new GitHubSanityCachedValue<>(); + + /** + * Creates a client API root object. + * + *

+ * Several different combinations of the login/oauthAccessToken/password parameters are allowed to represent + * different ways of authentication. + * + *

+ *
Log in anonymously + *
Leave all three parameters null and you will be making HTTP requests without any authentication. + * + *
Log in with password + *
Specify the login and password, then leave oauthAccessToken null. This will use the HTTP BASIC auth with the + * GitHub API. + * + *
Log in with OAuth token + *
Specify oauthAccessToken, and optionally specify the login. Leave password null. This will send OAuth token + * to the GitHub API. If the login parameter is null, The constructor makes an API call to figure out the user name + * that owns the token. + * + *
Log in with JWT token + *
Specify jwtToken. Leave password null. This will send JWT token to the GitHub API via the Authorization HTTP + * header. Please note that only operations in which permissions have been previously configured and accepted during + * the GitHub App will be executed successfully. + *
+ * + * @param apiUrl + * The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or + * "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has /api/v3 in the URL. For + * historical reasons, this parameter still accepts the bare domain name, but that's considered + * deprecated. + * @param connector + * a connector + * @param rateLimitHandler + * rateLimitHandler + * @param abuseLimitHandler + * abuseLimitHandler + * @param rateLimitChecker + * rateLimitChecker + * @param authorizationProvider + * a authorization provider + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @SuppressFBWarnings(value = { "CT_CONSTRUCTOR_THROW" }, justification = "internal constructor") + GitHub(String apiUrl, + GitHubConnector connector, + GitHubRateLimitHandler rateLimitHandler, + GitHubAbuseLimitHandler abuseLimitHandler, + GitHubRateLimitChecker rateLimitChecker, + AuthorizationProvider authorizationProvider) throws IOException { + if (authorizationProvider instanceof DependentAuthorizationProvider) { + ((DependentAuthorizationProvider) authorizationProvider).bind(this); + } else if (authorizationProvider instanceof ImmutableAuthorizationProvider + && authorizationProvider instanceof UserAuthorizationProvider) { + UserAuthorizationProvider provider = (UserAuthorizationProvider) authorizationProvider; + if (provider.getLogin() == null && provider.getEncodedAuthorization() != null + && provider.getEncodedAuthorization().startsWith("token")) { + authorizationProvider = new LoginLoadingUserAuthorizationProvider(provider, this); + } + } + + users = new ConcurrentHashMap<>(); + orgs = new ConcurrentHashMap<>(); + + this.client = new GitHubClient(apiUrl, + connector, + rateLimitHandler, + abuseLimitHandler, + rateLimitChecker, + authorizationProvider); + + // Ensure we have the login if it is available + // This preserves previously existing behavior. Consider removing in future. + if (authorizationProvider instanceof LoginLoadingUserAuthorizationProvider) { + ((LoginLoadingUserAuthorizationProvider) authorizationProvider).getLogin(); + } + } + + private GitHub(GitHubClient client) { + users = new ConcurrentHashMap<>(); + orgs = new ConcurrentHashMap<>(); + this.client = client; + } + + private static class LoginLoadingUserAuthorizationProvider implements UserAuthorizationProvider { + private final GitHub gitHub; + private final AuthorizationProvider authorizationProvider; + private boolean loginLoaded = false; + private String login; + + LoginLoadingUserAuthorizationProvider(AuthorizationProvider authorizationProvider, GitHub gitHub) { + this.gitHub = gitHub; + this.authorizationProvider = authorizationProvider; + } + + @Override + public String getEncodedAuthorization() throws IOException { + return authorizationProvider.getEncodedAuthorization(); + } + + @Override + public String getLogin() { + synchronized (this) { + if (!loginLoaded) { + loginLoaded = true; + try { + GHMyself u = gitHub.setMyself(); + if (u != null) { + login = u.getLogin(); + } + } catch (IOException e) { + } + } + return login; + } + } + } + /** * The Class DependentAuthorizationProvider. */ public static abstract class DependentAuthorizationProvider implements AuthorizationProvider { - private final AuthorizationProvider authorizationProvider; private GitHub baseGitHub; private GitHub gitHub; + private final AuthorizationProvider authorizationProvider; /** * An AuthorizationProvider that requires an authenticated GitHub instance to provide its authorization. @@ -75,18 +206,6 @@ protected DependentAuthorizationProvider(AuthorizationProvider authorizationProv this.authorizationProvider = authorizationProvider; } - /** - * Git hub. - * - * @return the git hub - */ - protected synchronized final GitHub gitHub() { - if (gitHub == null) { - gitHub = new GitHub.AuthorizationRefreshGitHubWrapper(this.baseGitHub, authorizationProvider); - } - return gitHub; - } - /** * Binds this authorization provider to a github instance. * @@ -101,6 +220,18 @@ synchronized void bind(GitHub github) { } this.baseGitHub = github; } + + /** + * Git hub. + * + * @return the git hub + */ + protected synchronized final GitHub gitHub() { + if (gitHub == null) { + gitHub = new GitHub.AuthorizationRefreshGitHubWrapper(this.baseGitHub, authorizationProvider); + } + return gitHub; + } } private static class AuthorizationRefreshGitHubWrapper extends GitHub { @@ -130,41 +261,6 @@ Requester createRequest() { } } - private static class LoginLoadingUserAuthorizationProvider implements UserAuthorizationProvider { - private final AuthorizationProvider authorizationProvider; - private final GitHub gitHub; - private String login; - private boolean loginLoaded = false; - - LoginLoadingUserAuthorizationProvider(AuthorizationProvider authorizationProvider, GitHub gitHub) { - this.gitHub = gitHub; - this.authorizationProvider = authorizationProvider; - } - - @Override - public String getEncodedAuthorization() throws IOException { - return authorizationProvider.getEncodedAuthorization(); - } - - @Override - public String getLogin() { - synchronized (this) { - if (!loginLoaded) { - loginLoaded = true; - try { - GHMyself u = gitHub.setMyself(); - if (u != null) { - login = u.getLogin(); - } - } catch (IOException e) { - } - } - return login; - } - } - } - private static final Logger LOGGER = Logger.getLogger(GitHub.class.getName()); - /** * Obtains the credential from "~/.github" or from the System Environment Properties. * @@ -177,8 +273,13 @@ public static GitHub connect() throws IOException { } /** - * Connect git hub. + * Version that connects to GitHub Enterprise. * + * @param apiUrl + * The URL of GitHub (or GitHub Enterprise) API endpoint, such as "https://api.github.com" or + * "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has /api/v3 in the URL. For + * historical reasons, this parameter still accepts the bare domain name, but that's considered + * deprecated. * @param login * the login * @param oauthAccessToken @@ -187,46 +288,14 @@ public static GitHub connect() throws IOException { * @throws IOException * the io exception */ - public static GitHub connect(String login, String oauthAccessToken) throws IOException { - return new GitHubBuilder().withOAuthToken(oauthAccessToken, login).build(); - } - - /** - * Connects to GitHub anonymously. - *

- * All operations that require authentication will fail. - * - * @return the git hub - * @throws IOException - * the io exception - */ - public static GitHub connectAnonymously() throws IOException { - return new GitHubBuilder().build(); - } - - /** - * Connects to GitHub Enterprise anonymously. - *

- * All operations that require authentication will fail. - * - * @param apiUrl - * the api url - * @return the git hub - * @throws IOException - * the io exception - */ - public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOException { - return new GitHubBuilder().withEndpoint(apiUrl).build(); + public static GitHub connectToEnterpriseWithOAuth(String apiUrl, String login, String oauthAccessToken) + throws IOException { + return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken, login).build(); } /** - * Version that connects to GitHub Enterprise. + * Connect git hub. * - * @param apiUrl - * The URL of GitHub (or GitHub Enterprise) API endpoint, such as "https://api.github.com" or - * "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has /api/v3 in the URL. For - * historical reasons, this parameter still accepts the bare domain name, but that's considered - * deprecated. * @param login * the login * @param oauthAccessToken @@ -235,9 +304,8 @@ public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOExce * @throws IOException * the io exception */ - public static GitHub connectToEnterpriseWithOAuth(String apiUrl, String login, String oauthAccessToken) - throws IOException { - return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken, login).build(); + public static GitHub connect(String login, String oauthAccessToken) throws IOException { + return new GitHubBuilder().withOAuthToken(oauthAccessToken, login).build(); } /** @@ -269,37 +337,31 @@ public static GitHub connectUsingOAuth(String githubServer, String oauthAccessTo } /** - * Gets an {@link ObjectReader} that can be used to convert JSON into library data objects. - * - * If you must manually create library data objects from JSON, the {@link ObjectReader} returned by this method is - * the only supported way of doing so. - * - * WARNING: Objects generated from this method have limited functionality. They will not throw when being crated - * from valid JSON matching the expected object, but they are not guaranteed to be usable beyond that. Use with - * extreme caution. + * Connects to GitHub anonymously. + *

+ * All operations that require authentication will fail. * - * @return an {@link ObjectReader} instance that can be further configured. + * @return the git hub + * @throws IOException + * the io exception */ - @Nonnull - public static ObjectReader getMappingObjectReader() { - return GitHubClient.getMappingObjectReader(GitHub.offline()); + public static GitHub connectAnonymously() throws IOException { + return new GitHubBuilder().build(); } /** - * Gets an {@link ObjectWriter} that can be used to convert data objects in this library to JSON. - * - * If you must convert data object in this library to JSON, the {@link ObjectWriter} returned by this method is the - * only supported way of doing so. This {@link ObjectWriter} can be used to convert any library data object to JSON - * without throwing an exception. - * - * WARNING: While the JSON generated is generally expected to be stable, it is not part of the API of this library - * and may change without warning. Use with extreme caution. + * Connects to GitHub Enterprise anonymously. + *

+ * All operations that require authentication will fail. * - * @return an {@link ObjectWriter} instance that can be further configured. + * @param apiUrl + * the api url + * @return the git hub + * @throws IOException + * the io exception */ - @Nonnull - public static ObjectWriter getMappingObjectWriter() { - return GitHubClient.getMappingObjectWriter(); + public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOException { + return new GitHubBuilder().withEndpoint(apiUrl).build(); } /** @@ -319,357 +381,238 @@ public static GitHub offline() { } } - @Nonnull - private final GitHubClient client; - - @CheckForNull - private GHMyself myself; - - private final ConcurrentMap orgs; - - @Nonnull - private final GitHubSanityCachedValue sanityCachedMeta = new GitHubSanityCachedValue<>(); - - private final ConcurrentMap users; - - private GitHub(GitHubClient client) { - users = new ConcurrentHashMap<>(); - orgs = new ConcurrentHashMap<>(); - this.client = client; + /** + * Is this an anonymous connection. + * + * @return {@code true} if operations that require authentication will fail. + */ + public boolean isAnonymous() { + return client.isAnonymous(); } /** - * Creates a client API root object. - * - *

- * Several different combinations of the login/oauthAccessToken/password parameters are allowed to represent - * different ways of authentication. - * - *

- *
Log in anonymously - *
Leave all three parameters null and you will be making HTTP requests without any authentication. - * - *
Log in with password - *
Specify the login and password, then leave oauthAccessToken null. This will use the HTTP BASIC auth with the - * GitHub API. - * - *
Log in with OAuth token - *
Specify oauthAccessToken, and optionally specify the login. Leave password null. This will send OAuth token - * to the GitHub API. If the login parameter is null, The constructor makes an API call to figure out the user name - * that owns the token. - * - *
Log in with JWT token - *
Specify jwtToken. Leave password null. This will send JWT token to the GitHub API via the Authorization HTTP - * header. Please note that only operations in which permissions have been previously configured and accepted during - * the GitHub App will be executed successfully. - *
+ * Is this an always offline "connection". * - * @param apiUrl - * The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or - * "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has /api/v3 in the URL. For - * historical reasons, this parameter still accepts the bare domain name, but that's considered - * deprecated. - * @param connector - * a connector - * @param rateLimitHandler - * rateLimitHandler - * @param abuseLimitHandler - * abuseLimitHandler - * @param rateLimitChecker - * rateLimitChecker - * @param authorizationProvider - * a authorization provider - * @throws IOException - * Signals that an I/O exception has occurred. + * @return {@code true} if this is an always offline "connection". */ - @SuppressFBWarnings(value = { "CT_CONSTRUCTOR_THROW" }, justification = "internal constructor") - GitHub(String apiUrl, - GitHubConnector connector, - GitHubRateLimitHandler rateLimitHandler, - GitHubAbuseLimitHandler abuseLimitHandler, - GitHubRateLimitChecker rateLimitChecker, - AuthorizationProvider authorizationProvider) throws IOException { - if (authorizationProvider instanceof DependentAuthorizationProvider) { - ((DependentAuthorizationProvider) authorizationProvider).bind(this); - } else if (authorizationProvider instanceof ImmutableAuthorizationProvider - && authorizationProvider instanceof UserAuthorizationProvider) { - UserAuthorizationProvider provider = (UserAuthorizationProvider) authorizationProvider; - if (provider.getLogin() == null && provider.getEncodedAuthorization() != null - && provider.getEncodedAuthorization().startsWith("token")) { - authorizationProvider = new LoginLoadingUserAuthorizationProvider(provider, this); - } - } - - users = new ConcurrentHashMap<>(); - orgs = new ConcurrentHashMap<>(); - - this.client = new GitHubClient(apiUrl, - connector, - rateLimitHandler, - abuseLimitHandler, - rateLimitChecker, - authorizationProvider); - - // Ensure we have the login if it is available - // This preserves previously existing behavior. Consider removing in future. - if (authorizationProvider instanceof LoginLoadingUserAuthorizationProvider) { - ((LoginLoadingUserAuthorizationProvider) authorizationProvider).getLogin(); - } + public boolean isOffline() { + return client.isOffline(); } /** - * Tests the connection. - * - *

- * Verify that the API URL and credentials are valid to access this GitHub. - * - *

- * This method returns normally if the endpoint is reachable and verified to be GitHub API URL. Otherwise this - * method throws {@link IOException} to indicate the problem. + * Gets api url. * - * @throws IOException - * the io exception + * @return the api url */ - public void checkApiUrlValidity() throws IOException { - client.checkApiUrlValidity(); + public String getApiUrl() { + return client.getApiUrl(); } /** - * Check auth gh authorization. + * Gets the current full rate limit information from the server. * - * @param clientId - * the client id - * @param accessToken - * the access token - * @return the gh authorization + * For some versions of GitHub Enterprise, the {@code /rate_limit} endpoint returns a {@code 404 Not Found}. In that + * case, the most recent {@link GHRateLimit} information will be returned, including rate limit information returned + * in the response header for this request in if was present. + * + * For most use cases it would be better to implement a {@link RateLimitChecker} and add it via + * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. + * + * @return the rate limit * @throws IOException * the io exception - * @see Check an - * authorization */ - public GHAuthorization checkAuth(@Nonnull String clientId, @Nonnull String accessToken) throws IOException { - return createRequest().withUrlPath("/applications/" + clientId + "/tokens/" + accessToken) - .fetch(GHAuthorization.class); + @Nonnull + public GHRateLimit getRateLimit() throws IOException { + return client.getRateLimit(); } /** - * Creates a GitHub App from a manifest. + * Returns the most recently observed rate limit data or {@code null} if either there is no rate limit (for example + * GitHub Enterprise) or if no requests have been made. * - * @param code - * temporary code returned during the manifest flow - * @return the app - * @throws IOException - * the IO exception - * @see Get an - * app + * @return the most recently observed rate limit data or {@code null}. + * @deprecated implement a {@link RateLimitChecker} and add it via + * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. */ - public GHAppFromManifest createAppFromManifest(@Nonnull String code) throws IOException { - return createRequest().method("POST") - .withUrlPath("/app-manifests/" + code + "/conversions") - .fetch(GHAppFromManifest.class); + @Nonnull + @Deprecated + public GHRateLimit lastRateLimit() { + return client.lastRateLimit(); } /** - * Create gist gh gist builder. + * Gets the current rate limit while trying not to actually make any remote requests unless absolutely necessary. * - * @return the gh gist builder + * @return the current rate limit data. + * @throws IOException + * if we couldn't get the current rate limit data. + * @deprecated implement a {@link RateLimitChecker} and add it via + * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. */ - public GHGistBuilder createGist() { - return new GHGistBuilder(this); + @Nonnull + @Deprecated + public GHRateLimit rateLimit() throws IOException { + return client.rateLimit(RateLimitTarget.CORE); } /** - * Create or get auth gh authorization. + * Gets the {@link GHUser} that represents yourself. * - * @param clientId - * the client id - * @param clientSecret - * the client secret - * @param scopes - * the scopes - * @param note - * the note - * @param noteUrl - * the note url - * @return the gh authorization + * @return the myself * @throws IOException * the io exception - * @see docs */ - public GHAuthorization createOrGetAuth(String clientId, - String clientSecret, - List scopes, - String note, - String noteUrl) throws IOException { - Requester requester = createRequest().with("client_secret", clientSecret) - .with("scopes", scopes) - .with("note", note) - .with("note_url", noteUrl); - - return requester.method("PUT").withUrlPath("/authorizations/clients/" + clientId).fetch(GHAuthorization.class); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") + public GHMyself getMyself() throws IOException { + client.requireCredential(); + return setMyself(); } - /** - * Starts a builder that creates a new repository. - * - *

- * You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()} to - * finally create a repository. - * - * @param name - * the name - * @return the gh create repository builder - */ - public GHCreateRepositoryBuilder createRepository(String name) { - return new GHCreateRepositoryBuilder(name, this, "/user/repos"); + private GHMyself setMyself() throws IOException { + synchronized (this) { + if (this.myself == null) { + this.myself = createRequest().withUrlPath("/user").fetch(GHMyself.class); + } + return myself; + } } /** - * Creates a new authorization. - *

- * The token created can be then used for {@link GitHub#connectUsingOAuth(String)} in the future. + * Obtains the object that represents the named user. * - * @param scope - * the scope - * @param note - * the note - * @param noteUrl - * the note url - * @return the gh authorization + * @param login + * the login + * @return the user * @throws IOException * the io exception - * @see Documentation */ - public GHAuthorization createToken(Collection scope, String note, String noteUrl) throws IOException { - Requester requester = createRequest().with("scopes", scope).with("note", note).with("note_url", noteUrl); + public GHUser getUser(String login) throws IOException { + GHUser u = users.get(login); + if (u == null) { + u = createRequest().withUrlPath("/users/" + login).fetch(GHUser.class); + users.put(u.getLogin(), u); + } + return u; + } - return requester.method("POST").withUrlPath("/authorizations").fetch(GHAuthorization.class); + /** + * clears all cached data in order for external changes (modifications and del) to be reflected. + */ + public void refreshCache() { + users.clear(); + orgs.clear(); } /** - * Creates a new authorization using an OTP. - *

- * Start by running createToken, if exception is thrown, prompt for OTP from user - *

- * Once OTP is received, call this token request - *

- * The token created can be then used for {@link GitHub#connectUsingOAuth(String)} in the future. + * Interns the given {@link GHUser}. * - * @param scope - * the scope - * @param note - * the note - * @param noteUrl - * the note url - * @param OTP - * the otp - * @return the gh authorization - * @throws IOException - * the io exception - * @see Documentation + * @param orig + * the orig + * @return the user */ - public GHAuthorization createToken(Collection scope, String note, String noteUrl, Supplier OTP) - throws IOException { - try { - return createToken(scope, note, noteUrl); - } catch (GHOTPRequiredException ex) { - String OTPstring = OTP.get(); - Requester requester = createRequest().with("scopes", scope).with("note", note).with("note_url", noteUrl); - // Add the OTP from the user - requester.setHeader("x-github-otp", OTPstring); - return requester.method("POST").withUrlPath("/authorizations").fetch(GHAuthorization.class); + protected GHUser getUser(GHUser orig) { + GHUser u = users.get(orig.getLogin()); + if (u == null) { + users.put(orig.getLogin(), orig); + return orig; } + return u; } /** - * Delete auth. + * Gets {@link GHOrganization} specified by name. * - * @param id - * the id + * @param name + * the name + * @return the organization * @throws IOException * the io exception - * @see Delete an - * authorization */ - public void deleteAuth(long id) throws IOException { - createRequest().method("DELETE").withUrlPath("/authorizations/" + id).send(); + public GHOrganization getOrganization(String name) throws IOException { + GHOrganization o = orgs.get(name); + if (o == null) { + o = createRequest().withUrlPath("/orgs/" + name).fetch(GHOrganization.class); + orgs.put(name, o); + } + return o; } /** - * Gets api url. + * Gets a list of all organizations. * - * @return the api url + * @return the paged iterable */ - public String getApiUrl() { - return client.getApiUrl(); + public PagedIterable listOrganizations() { + return listOrganizations(null); } /** - * Returns the GitHub App associated with the authentication credentials used. - *

- * You must use a JWT to access this endpoint. + * Gets a list of all organizations starting after the organization identifier specified by 'since'. * - * @return the app - * @throws IOException - * the io exception - * @see Get the authenticated - * GitHub App + * @param since + * the since + * @return the paged iterable + * @see List All Orgs - Parameters */ - public GHApp getApp() throws IOException { - return createRequest().withUrlPath("/app").fetch(GHApp.class); + public PagedIterable listOrganizations(final String since) { + return createRequest().with("since", since) + .withUrlPath("/organizations") + .toIterable(GHOrganization[].class, null); } /** - * Returns the GitHub App identified by the given slug + * Gets the repository object from 'owner/repo' string that GitHub calls as "repository name". * - * @param slug - * the slug of the application - * @return the app + * @param name + * the name + * @return the repository * @throws IOException - * the IO exception - * @see Get an app + * the io exception + * @see GHRepository#getName() GHRepository#getName() */ - public GHApp getApp(@Nonnull String slug) throws IOException { - return createRequest().withUrlPath("/apps/" + slug).fetch(GHApp.class); + public GHRepository getRepository(String name) throws IOException { + String[] tokens = name.split("/"); + if (tokens.length != 2) { + throw new IllegalArgumentException("Repository name must be in format owner/repo"); + } + return GHRepository.read(this, tokens[0], tokens[1]); } /** - * Public events visible to you. Equivalent of what's displayed on https://github.com/ + * Gets the repository object from its ID. * - * @return the events + * @param id + * the id + * @return the repository by id * @throws IOException * the io exception */ - public List getEvents() throws IOException { - return createRequest().withUrlPath("/events").toIterable(GHEventInfo[].class, null).toList(); + public GHRepository getRepositoryById(long id) throws IOException { + return createRequest().withUrlPath("/repositories/" + id).fetch(GHRepository.class); } /** - * Gets a single gist by ID. + * Returns a list of popular open source licenses. * - * @param id - * the id - * @return the gist + * @return a list of popular open source licenses * @throws IOException * the io exception + * @see GitHub API - Licenses */ - public GHGist getGist(String id) throws IOException { - return createRequest().withUrlPath("/gists/" + id).fetch(GHGist.class); + public PagedIterable listLicenses() throws IOException { + return createRequest().withUrlPath("/licenses").toIterable(GHLicense[].class, null); } /** - * Returns the GitHub App Installation associated with the authentication credentials used. - *

- * You must use an installation token to access this endpoint; otherwise consider {@link #getApp()} and its various - * ways of retrieving installations. + * Returns a list of all users. * - * @return the app - * @see GitHub App installations + * @return the paged iterable + * @throws IOException + * the io exception */ - public GHAuthenticatedAppInstallation getInstallation() { - return new GHAuthenticatedAppInstallation(this); + public PagedIterable listUsers() throws IOException { + return createRequest().withUrlPath("/users").toIterable(GHUser[].class, null); } /** @@ -687,16 +630,20 @@ public GHLicense getLicense(String key) throws IOException { } /** - * Provides a list of GitHub's IP addresses. + * Returns a list all plans for your Marketplace listing + *

+ * GitHub Apps must use a JWT to access this endpoint. + *

+ * OAuth Apps must use basic authentication with their client ID and client secret to access this endpoint. * - * @return an instance of {@link GHMeta} + * @return the paged iterable * @throws IOException - * if the credentials supplied are invalid or if you're trying to access it as a GitHub App via the JWT - * authentication - * @see Get Meta + * the io exception + * @see List + * Plans */ - public GHMeta getMeta() throws IOException { - return this.sanityCachedMeta.get(() -> createRequest().withUrlPath("/meta").fetch(GHMeta.class)); + public PagedIterable listMarketplacePlans() throws IOException { + return createRequest().withUrlPath("/marketplace_listing/plans").toIterable(GHMarketplacePlan[].class, null); } /** @@ -712,6 +659,28 @@ public List getMyInvitations() throws IOException { .toList(); } + /** + * This method returns shallowly populated organizations. + *

+ * To retrieve full organization details, you need to call {@link #getOrganization(String)} TODO: make this + * automatic. + * + * @return the my organizations + * @throws IOException + * the io exception + */ + public Map getMyOrganizations() throws IOException { + GHOrganization[] orgs = createRequest().withUrlPath("/user/orgs") + .toIterable(GHOrganization[].class, null) + .toArray(); + Map r = new HashMap<>(); + for (GHOrganization o : orgs) { + // don't put 'o' into orgs because they are shallow + r.put(o.getLogin(), o); + } + return r; + } + /** * Returns only active subscriptions. *

@@ -721,31 +690,47 @@ public List getMyInvitations() throws IOException { * OAuth Apps must authenticate using an OAuth token. * * @return the paged iterable of GHMarketplaceUserPurchase - * @see Get a - * user's Marketplace purchases + * @throws IOException + * the io exception + * @see Get a user's + * Marketplace purchases */ - public PagedIterable getMyMarketplacePurchases() { + public PagedIterable getMyMarketplacePurchases() throws IOException { return createRequest().withUrlPath("/user/marketplace_purchases") .toIterable(GHMarketplaceUserPurchase[].class, null); } /** - * This method returns shallowly populated organizations. + * Alias for {@link #getUserPublicOrganizations(String)}. + * + * @param user + * the user + * @return the user public organizations + * @throws IOException + * the io exception + */ + public Map getUserPublicOrganizations(GHUser user) throws IOException { + return getUserPublicOrganizations(user.getLogin()); + } + + /** + * This method returns a shallowly populated organizations. *

- * To retrieve full organization details, you need to call {@link #getOrganization(String)} TODO: make this - * automatic. + * To retrieve full organization details, you need to call {@link #getOrganization(String)} * - * @return the my organizations + * @param login + * the user to retrieve public Organization membership information for + * @return the public Organization memberships for the user * @throws IOException * the io exception */ - public Map getMyOrganizations() throws IOException { - GHOrganization[] orgs = createRequest().withUrlPath("/user/orgs") + public Map getUserPublicOrganizations(String login) throws IOException { + GHOrganization[] orgs = createRequest().withUrlPath("/users/" + login + "/orgs") .toIterable(GHOrganization[].class, null) .toArray(); Map r = new HashMap<>(); for (GHOrganization o : orgs) { - // don't put 'o' into orgs because they are shallow + // don't put 'o' into orgs cache because they are shallow records r.put(o.getLogin(), o); } return r; @@ -778,203 +763,305 @@ public Map> getMyTeams() throws IOException { } /** - * Gets the {@link GHUser} that represents yourself. + * Public events visible to you. Equivalent of what's displayed on https://github.com/ * - * @return the myself + * @return the events * @throws IOException * the io exception */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Expected") - public GHMyself getMyself() throws IOException { - client.requireCredential(); - return setMyself(); + public List getEvents() throws IOException { + return createRequest().withUrlPath("/events").toIterable(GHEventInfo[].class, null).toList(); } /** - * Gets {@link GHOrganization} specified by name. + * List public events for a user + * see + * API documentation * - * @param name - * the name - * @return the organization + * @param login + * the login (user) to look public events for + * @return the events * @throws IOException * the io exception */ - public GHOrganization getOrganization(String name) throws IOException { - GHOrganization o = orgs.get(name); - if (o == null) { - o = createRequest().withUrlPath("/orgs/" + name).fetch(GHOrganization.class); - orgs.put(name, o); - } - return o; + public List getUserPublicEvents(String login) throws IOException { + return createRequest().withUrlPath("/users/" + login + "/events/public") + .toIterable(GHEventInfo[].class, null) + .toList(); } /** - * Gets project. + * Gets a single gist by ID. * * @param id * the id - * @return the project + * @return the gist + * @throws IOException + * the io exception + */ + public GHGist getGist(String id) throws IOException { + return createRequest().withUrlPath("/gists/" + id).fetch(GHGist.class); + } + + /** + * Create gist gh gist builder. + * + * @return the gh gist builder + */ + public GHGistBuilder createGist() { + return new GHGistBuilder(this); + } + + /** + * Parses the GitHub event object. + *

+ * This is primarily intended for receiving a POST HTTP call from a hook. Unfortunately, hook script payloads aren't + * self-descriptive, so you need to know the type of the payload you are expecting. + * + * @param + * the type parameter + * @param r + * the r + * @param type + * the type + * @return the t + * @throws IOException + * the io exception + */ + public T parseEventPayload(Reader r, Class type) throws IOException { + T t = GitHubClient.getMappingObjectReader(this).forType(type).readValue(r); + t.lateBind(); + return t; + } + + /** + * Starts a builder that creates a new repository. + * + *

+ * You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()} to + * finally create a repository. + * + * @param name + * the name + * @return the gh create repository builder + */ + public GHCreateRepositoryBuilder createRepository(String name) { + return new GHCreateRepositoryBuilder(name, this, "/user/repos"); + } + + /** + * Creates a new authorization. + *

+ * The token created can be then used for {@link GitHub#connectUsingOAuth(String)} in the future. + * + * @param scope + * the scope + * @param note + * the note + * @param noteUrl + * the note url + * @return the gh authorization + * @throws IOException + * the io exception + * @see Documentation + */ + public GHAuthorization createToken(Collection scope, String note, String noteUrl) throws IOException { + Requester requester = createRequest().with("scopes", scope).with("note", note).with("note_url", noteUrl); + + return requester.method("POST").withUrlPath("/authorizations").fetch(GHAuthorization.class); + } + + /** + * Creates a new authorization using an OTP. + *

+ * Start by running createToken, if exception is thrown, prompt for OTP from user + *

+ * Once OTP is received, call this token request + *

+ * The token created can be then used for {@link GitHub#connectUsingOAuth(String)} in the future. + * + * @param scope + * the scope + * @param note + * the note + * @param noteUrl + * the note url + * @param OTP + * the otp + * @return the gh authorization * @throws IOException * the io exception + * @see Documentation */ - public GHProject getProject(long id) throws IOException { - return createRequest().withUrlPath("/projects/" + id).fetch(GHProject.class); + public GHAuthorization createToken(Collection scope, String note, String noteUrl, Supplier OTP) + throws IOException { + try { + return createToken(scope, note, noteUrl); + } catch (GHOTPRequiredException ex) { + String OTPstring = OTP.get(); + Requester requester = createRequest().with("scopes", scope).with("note", note).with("note_url", noteUrl); + // Add the OTP from the user + requester.setHeader("x-github-otp", OTPstring); + return requester.method("POST").withUrlPath("/authorizations").fetch(GHAuthorization.class); + } } /** - * Gets project card. + * Create or get auth gh authorization. * - * @param id - * the id - * @return the project card + * @param clientId + * the client id + * @param clientSecret + * the client secret + * @param scopes + * the scopes + * @param note + * the note + * @param note_url + * the note url + * @return the gh authorization * @throws IOException * the io exception + * @see docs */ - public GHProjectCard getProjectCard(long id) throws IOException { - return createRequest().withUrlPath("/projects/columns/cards/" + id).fetch(GHProjectCard.class).lateBind(this); + public GHAuthorization createOrGetAuth(String clientId, + String clientSecret, + List scopes, + String note, + String note_url) throws IOException { + Requester requester = createRequest().with("client_secret", clientSecret) + .with("scopes", scopes) + .with("note", note) + .with("note_url", note_url); + + return requester.method("PUT").withUrlPath("/authorizations/clients/" + clientId).fetch(GHAuthorization.class); } /** - * Gets project column. + * Delete auth. * * @param id * the id - * @return the project column * @throws IOException * the io exception + * @see Delete an + * authorization */ - public GHProjectColumn getProjectColumn(long id) throws IOException { - return createRequest().withUrlPath("/projects/columns/" + id).fetch(GHProjectColumn.class).lateBind(this); + public void deleteAuth(long id) throws IOException { + createRequest().method("DELETE").withUrlPath("/authorizations/" + id).send(); } /** - * Gets the current full rate limit information from the server. - * - * For some versions of GitHub Enterprise, the {@code /rate_limit} endpoint returns a {@code 404 Not Found}. In that - * case, the most recent {@link GHRateLimit} information will be returned, including rate limit information returned - * in the response header for this request in if was present. - * - * For most use cases it would be better to implement a {@link RateLimitChecker} and add it via - * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. + * Check auth gh authorization. * - * @return the rate limit + * @param clientId + * the client id + * @param accessToken + * the access token + * @return the gh authorization * @throws IOException * the io exception + * @see Check an + * authorization */ - @Nonnull - public GHRateLimit getRateLimit() throws IOException { - return client.getRateLimit(); + public GHAuthorization checkAuth(@Nonnull String clientId, @Nonnull String accessToken) throws IOException { + return createRequest().withUrlPath("/applications/" + clientId + "/tokens/" + accessToken) + .fetch(GHAuthorization.class); } /** - * Gets the repository object from 'owner/repo' string that GitHub calls as "repository name". + * Reset auth gh authorization. * - * @param name - * the name - * @return the repository + * @param clientId + * the client id + * @param accessToken + * the access token + * @return the gh authorization * @throws IOException * the io exception - * @see GHRepository#getName() GHRepository#getName() + * @see Reset an + * authorization */ - public GHRepository getRepository(String name) throws IOException { - String[] tokens = name.split("/"); - if (tokens.length != 2) { - throw new IllegalArgumentException("Repository name must be in format owner/repo"); - } - return GHRepository.read(this, tokens[0], tokens[1]); + public GHAuthorization resetAuth(@Nonnull String clientId, @Nonnull String accessToken) throws IOException { + return createRequest().method("POST") + .withUrlPath("/applications/" + clientId + "/tokens/" + accessToken) + .fetch(GHAuthorization.class); } /** - * Gets the repository object from its ID. + * Returns a list of all authorizations. * - * @param id - * the id - * @return the repository by id + * @return the paged iterable * @throws IOException * the io exception + * @see List your + * authorizations */ - public GHRepository getRepositoryById(long id) throws IOException { - return createRequest().withUrlPath("/repositories/" + id).fetch(GHRepository.class); + public PagedIterable listMyAuthorizations() throws IOException { + return createRequest().withUrlPath("/authorizations").toIterable(GHAuthorization[].class, null); } /** - * Obtains the object that represents the named user. + * Returns the GitHub App associated with the authentication credentials used. + *

+ * You must use a JWT to access this endpoint. * - * @param login - * the login - * @return the user + * @return the app * @throws IOException * the io exception + * @see Get the authenticated + * GitHub App */ - public GHUser getUser(String login) throws IOException { - GHUser u = users.get(login); - if (u == null) { - u = createRequest().withUrlPath("/users/" + login).fetch(GHUser.class); - users.put(u.getLogin(), u); - } - return u; + public GHApp getApp() throws IOException { + return createRequest().withUrlPath("/app").fetch(GHApp.class); } /** - * List public events for a user - * see - * API documentation + * Returns the GitHub App identified by the given slug * - * @param login - * the login (user) to look public events for - * @return the events + * @param slug + * the slug of the application + * @return the app * @throws IOException - * the io exception + * the IO exception + * @see Get an app */ - public List getUserPublicEvents(String login) throws IOException { - return createRequest().withUrlPath("/users/" + login + "/events/public") - .toIterable(GHEventInfo[].class, null) - .toList(); + public GHApp getApp(@Nonnull String slug) throws IOException { + return createRequest().withUrlPath("/apps/" + slug).fetch(GHApp.class); } /** - * Alias for {@link #getUserPublicOrganizations(String)}. + * Creates a GitHub App from a manifest. * - * @param user - * the user - * @return the user public organizations + * @param code + * temporary code returned during the manifest flow + * @return the app * @throws IOException - * the io exception + * the IO exception + * @see Get an + * app */ - public Map getUserPublicOrganizations(GHUser user) throws IOException { - return getUserPublicOrganizations(user.getLogin()); + public GHAppFromManifest createAppFromManifest(@Nonnull String code) throws IOException { + return createRequest().method("POST") + .withUrlPath("/app-manifests/" + code + "/conversions") + .fetch(GHAppFromManifest.class); } /** - * This method returns a shallowly populated organizations. + * Returns the GitHub App Installation associated with the authentication credentials used. *

- * To retrieve full organization details, you need to call {@link #getOrganization(String)} + * You must use an installation token to access this endpoint; otherwise consider {@link #getApp()} and its various + * ways of retrieving installations. * - * @param login - * the user to retrieve public Organization membership information for - * @return the public Organization memberships for the user + * @return the app * @throws IOException * the io exception + * @see GitHub App installations */ - public Map getUserPublicOrganizations(String login) throws IOException { - GHOrganization[] orgs = createRequest().withUrlPath("/users/" + login + "/orgs") - .toIterable(GHOrganization[].class, null) - .toArray(); - Map r = new HashMap<>(); - for (GHOrganization o : orgs) { - // don't put 'o' into orgs cache because they are shallow records - r.put(o.getLogin(), o); - } - return r; - } - - /** - * Is this an anonymous connection. - * - * @return {@code true} if operations that require authentication will fail. - */ - public boolean isAnonymous() { - return client.isAnonymous(); + public GHAuthenticatedAppInstallation getInstallation() throws IOException { + return new GHAuthenticatedAppInstallation(this); } /** @@ -987,170 +1074,157 @@ public boolean isCredentialValid() { } /** - * Is this an always offline "connection". - * - * @return {@code true} if this is an always offline "connection". - */ - public boolean isOffline() { - return client.isOffline(); - } - - /** - * Returns the most recently observed rate limit data or {@code null} if either there is no rate limit (for example - * GitHub Enterprise) or if no requests have been made. + * Provides a list of GitHub's IP addresses. * - * @return the most recently observed rate limit data or {@code null}. - * @deprecated implement a {@link RateLimitChecker} and add it via - * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. + * @return an instance of {@link GHMeta} + * @throws IOException + * if the credentials supplied are invalid or if you're trying to access it as a GitHub App via the JWT + * authentication + * @see Get Meta */ - @Nonnull - @Deprecated - public GHRateLimit lastRateLimit() { - return client.lastRateLimit(); + public GHMeta getMeta() throws IOException { + return this.sanityCachedMeta.get(() -> createRequest().withUrlPath("/meta").fetch(GHMeta.class)); } /** - * This provides a dump of every public repository, in the order that they were created. + * Gets project. * - * @return the paged iterable - * @see documentation + * @param id + * the id + * @return the project + * @throws IOException + * the io exception */ - public PagedIterable listAllPublicRepositories() { - return listAllPublicRepositories(null); + public GHProject getProject(long id) throws IOException { + return createRequest().withUrlPath("/projects/" + id).fetch(GHProject.class); } /** - * This provides a dump of every public repository, in the order that they were created. + * Gets project column. * - * @param since - * The numeric ID of the last Repository that you’ve seen. See {@link GHRepository#getId()} - * @return the paged iterable - * @see documentation + * @param id + * the id + * @return the project column + * @throws IOException + * the io exception */ - public PagedIterable listAllPublicRepositories(final String since) { - return createRequest().with("since", since).withUrlPath("/repositories").toIterable(GHRepository[].class, null); + public GHProjectColumn getProjectColumn(long id) throws IOException { + return createRequest().withUrlPath("/projects/columns/" + id).fetch(GHProjectColumn.class).lateBind(this); } /** - * Returns a list of popular open source licenses. + * Gets project card. * - * @return a list of popular open source licenses - * @see GitHub API - Licenses + * @param id + * the id + * @return the project card + * @throws IOException + * the io exception */ - public PagedIterable listLicenses() { - return createRequest().withUrlPath("/licenses").toIterable(GHLicense[].class, null); + public GHProjectCard getProjectCard(long id) throws IOException { + return createRequest().withUrlPath("/projects/columns/cards/" + id).fetch(GHProjectCard.class).lateBind(this); } /** - * Returns a list all plans for your Marketplace listing + * Tests the connection. + * *

- * GitHub Apps must use a JWT to access this endpoint. + * Verify that the API URL and credentials are valid to access this GitHub. + * *

- * OAuth Apps must use basic authentication with their client ID and client secret to access this endpoint. + * This method returns normally if the endpoint is reachable and verified to be GitHub API URL. Otherwise this + * method throws {@link IOException} to indicate the problem. * - * @return the paged iterable - * @see List - * Plans + * @throws IOException + * the io exception */ - public PagedIterable listMarketplacePlans() { - return createRequest().withUrlPath("/marketplace_listing/plans").toIterable(GHMarketplacePlan[].class, null); + public void checkApiUrlValidity() throws IOException { + client.checkApiUrlValidity(); } /** - * Returns a list of all authorizations. + * Search commits. * - * @return the paged iterable - * @see List your - * authorizations + * @return the gh commit search builder */ - public PagedIterable listMyAuthorizations() { - return createRequest().withUrlPath("/authorizations").toIterable(GHAuthorization[].class, null); + public GHCommitSearchBuilder searchCommits() { + return new GHCommitSearchBuilder(this); } /** - * List all the notifications. + * Search issues. * - * @return the gh notification stream + * @return the gh issue search builder */ - public GHNotificationStream listNotifications() { - return new GHNotificationStream(this, "/notifications"); + public GHIssueSearchBuilder searchIssues() { + return new GHIssueSearchBuilder(this); } /** - * Gets a list of all organizations. + * Search for pull requests. * - * @return the paged iterable + * @return gh pull request search builder */ - public PagedIterable listOrganizations() { - return listOrganizations(null); + public GHPullRequestSearchBuilder searchPullRequests() { + return new GHPullRequestSearchBuilder(this); } /** - * Gets a list of all organizations starting after the organization identifier specified by 'since'. + * Search users. * - * @param since - * the since - * @return the paged iterable - * @see List All Orgs - Parameters + * @return the gh user search builder */ - public PagedIterable listOrganizations(final String since) { - return createRequest().with("since", since) - .withUrlPath("/organizations") - .toIterable(GHOrganization[].class, null); + public GHUserSearchBuilder searchUsers() { + return new GHUserSearchBuilder(this); } /** - * Returns a list of all users. + * Search repositories. * - * @return the paged iterable + * @return the gh repository search builder */ - public PagedIterable listUsers() { - return createRequest().withUrlPath("/users").toIterable(GHUser[].class, null); + public GHRepositorySearchBuilder searchRepositories() { + return new GHRepositorySearchBuilder(this); } /** - * Parses the GitHub event object. - *

- * This is primarily intended for receiving a POST HTTP call from a hook. Unfortunately, hook script payloads aren't - * self-descriptive, so you need to know the type of the payload you are expecting. + * Search content. * - * @param - * the type parameter - * @param r - * the r - * @param type - * the type - * @return the t - * @throws IOException - * the io exception + * @return the gh content search builder */ - public T parseEventPayload(Reader r, Class type) throws IOException { - T t = GitHubClient.getMappingObjectReader(this).forType(type).readValue(r); - t.lateBind(); - return t; + public GHContentSearchBuilder searchContent() { + return new GHContentSearchBuilder(this); } /** - * Gets the current rate limit while trying not to actually make any remote requests unless absolutely necessary. + * List all the notifications. * - * @return the current rate limit data. - * @throws IOException - * if we couldn't get the current rate limit data. - * @deprecated implement a {@link RateLimitChecker} and add it via - * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. + * @return the gh notification stream */ - @Nonnull - @Deprecated - public GHRateLimit rateLimit() throws IOException { - return client.rateLimit(RateLimitTarget.CORE); + public GHNotificationStream listNotifications() { + return new GHNotificationStream(this, "/notifications"); } /** - * clears all cached data in order for external changes (modifications and del) to be reflected. + * This provides a dump of every public repository, in the order that they were created. + * + * @return the paged iterable + * @see documentation */ - public void refreshCache() { - users.clear(); - orgs.clear(); + public PagedIterable listAllPublicRepositories() { + return listAllPublicRepositories(null); + } + + /** + * This provides a dump of every public repository, in the order that they were created. + * + * @param since + * The numeric ID of the last Repository that you’ve seen. See {@link GHRepository#getId()} + * @return the paged iterable + * @see documentation + */ + public PagedIterable listAllPublicRepositories(final String since) { + return createRequest().with("since", since).withUrlPath("/repositories").toIterable(GHRepository[].class, null); } /** @@ -1178,116 +1252,47 @@ public Reader renderMarkdown(String text) throws IOException { } /** - * Reset auth gh authorization. - * - * @param clientId - * the client id - * @param accessToken - * the access token - * @return the gh authorization - * @throws IOException - * the io exception - * @see Reset an - * authorization - */ - public GHAuthorization resetAuth(@Nonnull String clientId, @Nonnull String accessToken) throws IOException { - return createRequest().method("POST") - .withUrlPath("/applications/" + clientId + "/tokens/" + accessToken) - .fetch(GHAuthorization.class); - } - - /** - * Search commits. - * - * @return the gh commit search builder - */ - public GHCommitSearchBuilder searchCommits() { - return new GHCommitSearchBuilder(this); - } - - /** - * Search content. + * Gets an {@link ObjectWriter} that can be used to convert data objects in this library to JSON. * - * @return the gh content search builder - */ - public GHContentSearchBuilder searchContent() { - return new GHContentSearchBuilder(this); - } - - /** - * Search issues. + * If you must convert data object in this library to JSON, the {@link ObjectWriter} returned by this method is the + * only supported way of doing so. This {@link ObjectWriter} can be used to convert any library data object to JSON + * without throwing an exception. * - * @return the gh issue search builder - */ - public GHIssueSearchBuilder searchIssues() { - return new GHIssueSearchBuilder(this); - } - - /** - * Search for pull requests. + * WARNING: While the JSON generated is generally expected to be stable, it is not part of the API of this library + * and may change without warning. Use with extreme caution. * - * @return gh pull request search builder + * @return an {@link ObjectWriter} instance that can be further configured. */ - public GHPullRequestSearchBuilder searchPullRequests() { - return new GHPullRequestSearchBuilder(this); + @Nonnull + public static ObjectWriter getMappingObjectWriter() { + return GitHubClient.getMappingObjectWriter(); } /** - * Search repositories. + * Gets an {@link ObjectReader} that can be used to convert JSON into library data objects. * - * @return the gh repository search builder - */ - public GHRepositorySearchBuilder searchRepositories() { - return new GHRepositorySearchBuilder(this); - } - - /** - * Search users. + * If you must manually create library data objects from JSON, the {@link ObjectReader} returned by this method is + * the only supported way of doing so. * - * @return the gh user search builder - */ - public GHUserSearchBuilder searchUsers() { - return new GHUserSearchBuilder(this); - } - - private GHMyself setMyself() throws IOException { - synchronized (this) { - if (this.myself == null) { - this.myself = createRequest().withUrlPath("/user").fetch(GHMyself.class); - } - return myself; - } - } - - /** - * Interns the given {@link GHUser}. + * WARNING: Objects generated from this method have limited functionality. They will not throw when being crated + * from valid JSON matching the expected object, but they are not guaranteed to be usable beyond that. Use with + * extreme caution. * - * @param orig - * the orig - * @return the user + * @return an {@link ObjectReader} instance that can be further configured. */ - protected GHUser getUser(GHUser orig) { - GHUser u = users.get(orig.getLogin()); - if (u == null) { - users.put(orig.getLogin(), orig); - return orig; - } - return u; + @Nonnull + public static ObjectReader getMappingObjectReader() { + return GitHubClient.getMappingObjectReader(GitHub.offline()); } /** - * Creates a request to GitHub GraphQL API. + * Gets the client. * - * @param query - * the query for the GraphQL - * @return the requester + * @return the client */ @Nonnull - Requester createGraphQLRequest(String query) { - return createRequest().method("POST") - .rateLimit(RateLimitTarget.GRAPHQL) - .with("query", query) - .withUrlPath("/graphql"); + GitHubClient getClient() { + return client; } /** @@ -1306,24 +1311,16 @@ Requester createRequest() { return requester; } - /** - * Gets the client. - * - * @return the client - */ - @Nonnull - GitHubClient getClient() { - return client; - } - /** * Intern. * * @param user * the user * @return the GH user + * @throws IOException + * Signals that an I/O exception has occurred. */ - GHUser intern(GHUser user) { + GHUser intern(GHUser user) throws IOException { if (user != null) { // if we already have this user in our map, get it // if not, remember this new user @@ -1334,4 +1331,6 @@ GHUser intern(GHUser user) { } return user; } + + private static final Logger LOGGER = Logger.getLogger(GitHub.class.getName()); } diff --git a/src/main/java/org/kohsuke/github/GitHubAbuseLimitHandler.java b/src/main/java/org/kohsuke/github/GitHubAbuseLimitHandler.java index 2c05dd1455..30f3193c2f 100644 --- a/src/main/java/org/kohsuke/github/GitHubAbuseLimitHandler.java +++ b/src/main/java/org/kohsuke/github/GitHubAbuseLimitHandler.java @@ -19,78 +19,16 @@ * * @author Kohsuke Kawaguchi * @author Liam Newman - * @see GitHubBuilder#withAbuseLimitHandler(GitHubAbuseLimitHandler) + * @see GitHubBuilder#withAbuseLimitHandler(AbuseLimitHandler) GitHubBuilder#withRateLimitHandler(AbuseLimitHandler) * @see GitHubRateLimitHandler */ public abstract class GitHubAbuseLimitHandler extends GitHubConnectorResponseErrorHandler { - /** - * Fail immediately. - */ - public static final GitHubAbuseLimitHandler FAIL = new GitHubAbuseLimitHandler() { - @Override - public void onError(GitHubConnectorResponse connectorResponse) throws IOException { - throw new HttpException("Abuse limit reached", - connectorResponse.statusCode(), - connectorResponse.header("Status"), - connectorResponse.request().url().toString()) - .withResponseHeaderFields(connectorResponse.allHeaders()); - } - }; - - /** - * Wait until the API abuse "wait time" is passed. - */ - public static final GitHubAbuseLimitHandler WAIT = new GitHubAbuseLimitHandler() { - @Override - public void onError(GitHubConnectorResponse connectorResponse) throws IOException { - try { - Thread.sleep(parseWaitTime(connectorResponse)); - } catch (InterruptedException ex) { - throw (InterruptedIOException) new InterruptedIOException().initCause(ex); - } - } - }; - /** * On a wait, even if the response suggests a very short wait, wait for a minimum duration. */ private static final int MINIMUM_ABUSE_RETRY_MILLIS = 1000; - // If "Retry-After" missing, wait for unambiguously over one minute per GitHub guidance - static long DEFAULT_WAIT_MILLIS = Duration.ofSeconds(61).toMillis(); - - /* - * Exposed for testability. Given an http response, find the retry-after header field and parse it as either a - * number or a date (the spec allows both). If no header is found, wait for a reasonably amount of time. - */ - static long parseWaitTime(GitHubConnectorResponse connectorResponse) { - String v = connectorResponse.header("Retry-After"); - if (v == null) { - return DEFAULT_WAIT_MILLIS; - } - - try { - return Math.max(MINIMUM_ABUSE_RETRY_MILLIS, Duration.ofSeconds(Long.parseLong(v)).toMillis()); - } catch (NumberFormatException nfe) { - // The retry-after header could be a number in seconds, or an http-date - // We know it was a date if we got a number format exception :) - - // Don't use ZonedDateTime.now(), because the local and remote server times may not be in sync - // Instead, we can take advantage of the Date field in the response to see what time the remote server - // thinks it is - String dateField = connectorResponse.header("Date"); - ZonedDateTime now; - if (dateField != null) { - now = ZonedDateTime.parse(dateField, DateTimeFormatter.RFC_1123_DATE_TIME); - } else { - now = ZonedDateTime.now(); - } - ZonedDateTime zdt = ZonedDateTime.parse(v, DateTimeFormatter.RFC_1123_DATE_TIME); - return Math.max(MINIMUM_ABUSE_RETRY_MILLIS, ChronoUnit.MILLIS.between(now, zdt)); - } - } - /** * Create default GitHubAbuseLimitHandler instance */ @@ -98,36 +36,40 @@ public GitHubAbuseLimitHandler() { } /** - * Called when the library encounters HTTP error indicating that the API abuse limit is reached. - * - *

- * Any exception thrown from this method will cause the request to fail, and the caller of github-api will receive - * an exception. If this method returns normally, another request will be attempted. For that to make sense, the - * implementation needs to wait for some time. + * Checks if is error. * * @param connectorResponse - * Response information for this request. + * the connector response + * @return true, if is error * @throws IOException - * on failure - * @see API documentation from GitHub - * @see Dealing - * with abuse rate limits + * Signals that an I/O exception has occurred. + */ + @Override + boolean isError(@Nonnull GitHubConnectorResponse connectorResponse) { + return isTooManyRequests(connectorResponse) + || (isForbidden(connectorResponse) && hasRetryOrLimitHeader(connectorResponse)); + } + + /** + * Checks if the response status code is TOO_MANY_REQUESTS (429). * + * @param connectorResponse + * the response from the GitHub connector + * @return true if the status code is TOO_MANY_REQUESTS */ - public abstract void onError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException; + private boolean isTooManyRequests(GitHubConnectorResponse connectorResponse) { + return connectorResponse.statusCode() == TOO_MANY_REQUESTS; + } /** - * Checks if the response contains a specific header. + * Checks if the response status code is HTTP_FORBIDDEN (403). * * @param connectorResponse * the response from the GitHub connector - * @param headerName - * the name of the header to check for - * @return true if the specified header is present + * @return true if the status code is HTTP_FORBIDDEN */ - private boolean hasHeader(GitHubConnectorResponse connectorResponse, String headerName) { - return connectorResponse.header(headerName) != null; + private boolean isForbidden(GitHubConnectorResponse connectorResponse) { + return connectorResponse.statusCode() == HTTP_FORBIDDEN; } /** @@ -139,48 +81,105 @@ private boolean hasHeader(GitHubConnectorResponse connectorResponse, String head * the response from the GitHub connector * @return true if either "Retry-After" or "gh-limited-by" headers are present * @see GitHub - * API Rate Limiting Documentation + * "https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api?apiVersion=2022-11-28#handle-rate-limit-errors-appropriately */ private boolean hasRetryOrLimitHeader(GitHubConnectorResponse connectorResponse) { return hasHeader(connectorResponse, "Retry-After") || hasHeader(connectorResponse, "gh-limited-by"); } /** - * Checks if the response status code is HTTP_FORBIDDEN (403). + * Checks if the response contains a specific header. * * @param connectorResponse * the response from the GitHub connector - * @return true if the status code is HTTP_FORBIDDEN + * @param headerName + * the name of the header to check for + * @return true if the specified header is present */ - private boolean isForbidden(GitHubConnectorResponse connectorResponse) { - return connectorResponse.statusCode() == HTTP_FORBIDDEN; + private boolean hasHeader(GitHubConnectorResponse connectorResponse, String headerName) { + return connectorResponse.header(headerName) != null; } /** - * Checks if the response status code is TOO_MANY_REQUESTS (429). + * Called when the library encounters HTTP error indicating that the API abuse limit is reached. + * + *

+ * Any exception thrown from this method will cause the request to fail, and the caller of github-api will receive + * an exception. If this method returns normally, another request will be attempted. For that to make sense, the + * implementation needs to wait for some time. * * @param connectorResponse - * the response from the GitHub connector - * @return true if the status code is TOO_MANY_REQUESTS + * Response information for this request. + * @throws IOException + * on failure + * @see API documentation from GitHub + * @see Dealing + * with abuse rate limits + * */ - private boolean isTooManyRequests(GitHubConnectorResponse connectorResponse) { - return connectorResponse.statusCode() == TOO_MANY_REQUESTS; - } + public abstract void onError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException; /** - * Checks if is error. - * - * @param connectorResponse - * the connector response - * @return true, if is error - * @throws IOException - * Signals that an I/O exception has occurred. + * Wait until the API abuse "wait time" is passed. */ - @Override - boolean isError(@Nonnull GitHubConnectorResponse connectorResponse) { - return isTooManyRequests(connectorResponse) - || (isForbidden(connectorResponse) && hasRetryOrLimitHeader(connectorResponse)); + public static final GitHubAbuseLimitHandler WAIT = new GitHubAbuseLimitHandler() { + @Override + public void onError(GitHubConnectorResponse connectorResponse) throws IOException { + try { + Thread.sleep(parseWaitTime(connectorResponse)); + } catch (InterruptedException ex) { + throw (InterruptedIOException) new InterruptedIOException().initCause(ex); + } + } + }; + + /** + * Fail immediately. + */ + public static final GitHubAbuseLimitHandler FAIL = new GitHubAbuseLimitHandler() { + @Override + public void onError(GitHubConnectorResponse connectorResponse) throws IOException { + throw new HttpException("Abuse limit reached", + connectorResponse.statusCode(), + connectorResponse.header("Status"), + connectorResponse.request().url().toString()) + .withResponseHeaderFields(connectorResponse.allHeaders()); + } + }; + + // If "Retry-After" missing, wait for unambiguously over one minute per GitHub guidance + static long DEFAULT_WAIT_MILLIS = Duration.ofSeconds(61).toMillis(); + + /* + * Exposed for testability. Given an http response, find the retry-after header field and parse it as either a + * number or a date (the spec allows both). If no header is found, wait for a reasonably amount of time. + */ + static long parseWaitTime(GitHubConnectorResponse connectorResponse) { + String v = connectorResponse.header("Retry-After"); + if (v == null) { + return DEFAULT_WAIT_MILLIS; + } + + try { + return Math.max(MINIMUM_ABUSE_RETRY_MILLIS, Duration.ofSeconds(Long.parseLong(v)).toMillis()); + } catch (NumberFormatException nfe) { + // The retry-after header could be a number in seconds, or an http-date + // We know it was a date if we got a number format exception :) + + // Don't use ZonedDateTime.now(), because the local and remote server times may not be in sync + // Instead, we can take advantage of the Date field in the response to see what time the remote server + // thinks it is + String dateField = connectorResponse.header("Date"); + ZonedDateTime now; + if (dateField != null) { + now = ZonedDateTime.parse(dateField, DateTimeFormatter.RFC_1123_DATE_TIME); + } else { + now = ZonedDateTime.now(); + } + ZonedDateTime zdt = ZonedDateTime.parse(v, DateTimeFormatter.RFC_1123_DATE_TIME); + return Math.max(MINIMUM_ABUSE_RETRY_MILLIS, ChronoUnit.MILLIS.between(now, zdt)); + } } } diff --git a/src/main/java/org/kohsuke/github/GitHubBridgeAdapterObject.java b/src/main/java/org/kohsuke/github/GitHubBridgeAdapterObject.java deleted file mode 100644 index 3477c96013..0000000000 --- a/src/main/java/org/kohsuke/github/GitHubBridgeAdapterObject.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.kohsuke.github; - -import java.time.Instant; -import java.util.Date; - -/** - * Defines a base class that holds bridge adapter methods. - * - * @author Liam Newman - */ -abstract class GitHubBridgeAdapterObject { - /** - * Instantiates a new git hub bridge adapter object. - */ - GitHubBridgeAdapterObject() { - } - - // Used by bridge method to convert Instant to Date - Object instantToDate(Instant value, Class type) { - if (value == null) - return null; - - return Date.from(value); - } -} diff --git a/src/main/java/org/kohsuke/github/GitHubBuilder.java b/src/main/java/org/kohsuke/github/GitHubBuilder.java index 3f762fd059..19f4c4a957 100644 --- a/src/main/java/org/kohsuke/github/GitHubBuilder.java +++ b/src/main/java/org/kohsuke/github/GitHubBuilder.java @@ -28,6 +28,67 @@ public class GitHubBuilder implements Cloneable { // for testing static File HOME_DIRECTORY = null; + // default scoped so unit tests can read them. + /** The endpoint. */ + /* private */ String endpoint = GitHubClient.GITHUB_URL; + + private GitHubConnector connector; + + private GitHubRateLimitHandler rateLimitHandler = GitHubRateLimitHandler.WAIT; + private GitHubAbuseLimitHandler abuseLimitHandler = GitHubAbuseLimitHandler.WAIT; + private GitHubRateLimitChecker rateLimitChecker = new GitHubRateLimitChecker(); + + /** The authorization provider. */ + /* private */ AuthorizationProvider authorizationProvider = AuthorizationProvider.ANONYMOUS; + + /** + * Instantiates a new Git hub builder. + */ + public GitHubBuilder() { + } + + /** + * First check if the credentials are configured in the environment. We use environment first because users are not + * likely to give required (full) permissions to their default key. + * + * If no user is specified it means there is no configuration present, so try using the ~/.github properties file. + ** + * If there is still no user it means there are no credentials defined and throw an IOException. + * + * @return the configured Builder from credentials defined on the system or in the environment. Otherwise returns + * null. + * + * @throws IOException + * If there are no credentials defined in the ~/.github properties file or the process environment. + */ + static GitHubBuilder fromCredentials() throws IOException { + Exception cause = null; + GitHubBuilder builder = null; + + builder = fromEnvironment(); + + if (builder.authorizationProvider != AuthorizationProvider.ANONYMOUS) + return builder; + + try { + builder = fromPropertyFile(); + + if (builder.authorizationProvider != AuthorizationProvider.ANONYMOUS) + return builder; + } catch (FileNotFoundException e) { + // fall through + cause = e; + } + throw (IOException) new IOException("Failed to resolve credentials from ~/.github or the environment.") + .initCause(cause); + } + + private static void loadIfSet(String envName, Properties p, String propName) { + String v = System.getenv(envName); + if (v != null) + p.put(propName, v); + } + /** * Creates {@link GitHubBuilder} by picking up coordinates from environment variables. * @@ -45,8 +106,10 @@ public class GitHubBuilder implements Cloneable { * See class javadoc for the relationship between these coordinates. * * @return the GitHubBuilder + * @throws IOException + * the io exception */ - public static GitHubBuilder fromEnvironment() { + public static GitHubBuilder fromEnvironment() throws IOException { Properties props = new Properties(); for (Entry e : System.getenv().entrySet()) { String name = e.getKey().toLowerCase(Locale.ENGLISH); @@ -57,29 +120,6 @@ public static GitHubBuilder fromEnvironment() { return fromProperties(props); } - /** - * From properties GitHubBuilder. - * - * @param props - * the props - * @return the GitHubBuilder - */ - public static GitHubBuilder fromProperties(Properties props) { - GitHubBuilder self = new GitHubBuilder(); - String oauth = props.getProperty("oauth"); - String jwt = props.getProperty("jwt"); - String login = props.getProperty("login"); - - if (oauth != null) { - self.withOAuthToken(oauth, login); - } - if (jwt != null) { - self.withJwtToken(jwt); - } - self.withEndpoint(props.getProperty("endpoint", GitHubClient.GITHUB_URL)); - return self; - } - /** * From property file GitHubBuilder. * @@ -92,6 +132,7 @@ public static GitHubBuilder fromPropertyFile() throws IOException { File propertyFile = new File(homeDir, ".github"); return fromPropertyFile(propertyFile.getPath()); } + /** * From property file GitHubBuilder. * @@ -113,113 +154,81 @@ public static GitHubBuilder fromPropertyFile(String propertyFileName) throws IOE return fromProperties(props); } - private static void loadIfSet(String envName, Properties p, String propName) { - String v = System.getenv(envName); - if (v != null) - p.put(propName, v); - } /** - * First check if the credentials are configured in the environment. We use environment first because users are not - * likely to give required (full) permissions to their default key. - * - * If no user is specified it means there is no configuration present, so try using the ~/.github properties file. - ** - * If there is still no user it means there are no credentials defined and throw an IOException. - * - * @return the configured Builder from credentials defined on the system or in the environment. Otherwise returns - * null. + * From properties GitHubBuilder. * - * @throws IOException - * If there are no credentials defined in the ~/.github properties file or the process environment. + * @param props + * the props + * @return the GitHubBuilder */ - static GitHubBuilder fromCredentials() throws IOException { - Exception cause = null; - GitHubBuilder builder = null; - - builder = fromEnvironment(); - - if (builder.authorizationProvider != AuthorizationProvider.ANONYMOUS) - return builder; - - try { - builder = fromPropertyFile(); + public static GitHubBuilder fromProperties(Properties props) { + GitHubBuilder self = new GitHubBuilder(); + String oauth = props.getProperty("oauth"); + String jwt = props.getProperty("jwt"); + String login = props.getProperty("login"); - if (builder.authorizationProvider != AuthorizationProvider.ANONYMOUS) - return builder; - } catch (FileNotFoundException e) { - // fall through - cause = e; + if (oauth != null) { + self.withOAuthToken(oauth, login); } - throw (IOException) new IOException("Failed to resolve credentials from ~/.github or the environment.") - .initCause(cause); + if (jwt != null) { + self.withJwtToken(jwt); + } + self.withEndpoint(props.getProperty("endpoint", GitHubClient.GITHUB_URL)); + return self; } - private GitHubAbuseLimitHandler abuseLimitHandler = GitHubAbuseLimitHandler.WAIT; - - private GitHubConnector connector; - - private GitHubRateLimitChecker rateLimitChecker = new GitHubRateLimitChecker(); - - private GitHubRateLimitHandler rateLimitHandler = GitHubRateLimitHandler.WAIT; - - /** The authorization provider. */ - /* private */ AuthorizationProvider authorizationProvider = AuthorizationProvider.ANONYMOUS; - - // default scoped so unit tests can read them. - /** The endpoint. */ - /* private */ String endpoint = GitHubClient.GITHUB_URL; - /** - * Instantiates a new Git hub builder. + * With endpoint GitHubBuilder. + * + * @param endpoint + * The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or + * "https://ghe.acme.com/api/v3". Note that GitHub Enterprise has /api/v3 in the URL. For + * historical reasons, this parameter still accepts the bare domain name, but that's considered + * deprecated. + * @return the GitHubBuilder */ - public GitHubBuilder() { + public GitHubBuilder withEndpoint(String endpoint) { + this.endpoint = endpoint; + return this; } /** - * Builds a {@link GitHub} instance. + * With o auth token GitHubBuilder. * - * @return the github - * @throws IOException - * the io exception + * @param oauthToken + * the oauth token + * @return the GitHubBuilder */ - public GitHub build() throws IOException { - return new GitHub(endpoint, - connector, - rateLimitHandler, - abuseLimitHandler, - rateLimitChecker, - authorizationProvider); + public GitHubBuilder withOAuthToken(String oauthToken) { + return withAuthorizationProvider(ImmutableAuthorizationProvider.fromOauthToken(oauthToken)); } /** - * Clone. + * With o auth token GitHubBuilder. * + * @param oauthToken + * the oauth token + * @param user + * the user * @return the GitHubBuilder */ - @Override - public GitHubBuilder clone() { - try { - return (GitHubBuilder) super.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException("Clone should be supported", e); - } + public GitHubBuilder withOAuthToken(String oauthToken, String user) { + return withAuthorizationProvider(ImmutableAuthorizationProvider.fromOauthToken(oauthToken, user)); } /** - * Adds a {@link GitHubAbuseLimitHandler} to this {@link GitHubBuilder}. - *

- * When a client sends too many requests in a short time span, GitHub may return an error and set a header telling - * the client to not make any more request for some period of time. If this happens, - * {@link GitHubAbuseLimitHandler#onError(GitHubConnectorResponse)} will be called. - *

+ * Configures a {@link AuthorizationProvider} for this builder * - * @param handler - * the handler + * There can be only one authorization provider per client instance. + * + * @param authorizationProvider + * the authorization provider * @return the GitHubBuilder + * */ - public GitHubBuilder withAbuseLimitHandler(GitHubAbuseLimitHandler handler) { - this.abuseLimitHandler = handler; + public GitHubBuilder withAuthorizationProvider(final AuthorizationProvider authorizationProvider) { + this.authorizationProvider = authorizationProvider; return this; } @@ -236,18 +245,14 @@ public GitHubBuilder withAppInstallationToken(String appInstallationToken) { } /** - * Configures a {@link AuthorizationProvider} for this builder - * - * There can be only one authorization provider per client instance. + * With jwt token GitHubBuilder. * - * @param authorizationProvider - * the authorization provider + * @param jwtToken + * the jwt token * @return the GitHubBuilder - * */ - public GitHubBuilder withAuthorizationProvider(final AuthorizationProvider authorizationProvider) { - this.authorizationProvider = authorizationProvider; - return this; + public GitHubBuilder withJwtToken(String jwtToken) { + return withAuthorizationProvider(ImmutableAuthorizationProvider.fromJwtToken(jwtToken)); } /** @@ -263,53 +268,47 @@ public GitHubBuilder withConnector(GitHubConnector connector) { } /** - * With endpoint GitHubBuilder. + * Adds a {@link GitHubRateLimitHandler} to this {@link GitHubBuilder}. + *

+ * GitHub allots a certain number of requests to each user or application per period of time (usually per hour). The + * number of requests remaining is returned in the response header and can also be requested using + * {@link GitHub#getRateLimit()}. This requests per interval is referred to as the "rate limit". + *

+ *

+ * When the remaining number of requests reaches zero, the next request will return an error. If this happens, + * {@link GitHubRateLimitHandler#onError(GitHubConnectorResponse)} will be called. + *

+ *

+ * NOTE: GitHub treats clients that exceed their rate limit very harshly. If possible, clients should avoid + * exceeding their rate limit. Consider adding a {@link RateLimitChecker} to automatically check the rate limit for + * each request and wait if needed. + *

* - * @param endpoint - * The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or - * "https://ghe.acme.com/api/v3". Note that GitHub Enterprise has /api/v3 in the URL. For - * historical reasons, this parameter still accepts the bare domain name, but that's considered - * deprecated. + * @param handler + * the handler * @return the GitHubBuilder + * @see #withRateLimitChecker(RateLimitChecker) */ - public GitHubBuilder withEndpoint(String endpoint) { - this.endpoint = endpoint; + public GitHubBuilder withRateLimitHandler(GitHubRateLimitHandler handler) { + this.rateLimitHandler = handler; return this; } /** - * With jwt token GitHubBuilder. - * - * @param jwtToken - * the jwt token - * @return the GitHubBuilder - */ - public GitHubBuilder withJwtToken(String jwtToken) { - return withAuthorizationProvider(ImmutableAuthorizationProvider.fromJwtToken(jwtToken)); - } - - /** - * With o auth token GitHubBuilder. - * - * @param oauthToken - * the oauth token - * @return the GitHubBuilder - */ - public GitHubBuilder withOAuthToken(String oauthToken) { - return withAuthorizationProvider(ImmutableAuthorizationProvider.fromOauthToken(oauthToken)); - } - - /** - * With o auth token GitHubBuilder. + * Adds a {@link GitHubAbuseLimitHandler} to this {@link GitHubBuilder}. + *

+ * When a client sends too many requests in a short time span, GitHub may return an error and set a header telling + * the client to not make any more request for some period of time. If this happens, + * {@link GitHubAbuseLimitHandler#onError(GitHubConnectorResponse)} will be called. + *

* - * @param oauthToken - * the oauth token - * @param user - * the user + * @param handler + * the handler * @return the GitHubBuilder */ - public GitHubBuilder withOAuthToken(String oauthToken, String user) { - return withAuthorizationProvider(ImmutableAuthorizationProvider.fromOauthToken(oauthToken, user)); + public GitHubBuilder withAbuseLimitHandler(GitHubAbuseLimitHandler handler) { + this.abuseLimitHandler = handler; + return this; } /** @@ -355,29 +354,32 @@ public GitHubBuilder withRateLimitChecker(@Nonnull RateLimitChecker rateLimitChe } /** - * Adds a {@link GitHubRateLimitHandler} to this {@link GitHubBuilder}. - *

- * GitHub allots a certain number of requests to each user or application per period of time (usually per hour). The - * number of requests remaining is returned in the response header and can also be requested using - * {@link GitHub#getRateLimit()}. This requests per interval is referred to as the "rate limit". - *

- *

- * When the remaining number of requests reaches zero, the next request will return an error. If this happens, - * {@link GitHubRateLimitHandler#onError(GitHubConnectorResponse)} will be called. - *

- *

- * NOTE: GitHub treats clients that exceed their rate limit very harshly. If possible, clients should avoid - * exceeding their rate limit. Consider adding a {@link RateLimitChecker} to automatically check the rate limit for - * each request and wait if needed. - *

+ * Builds a {@link GitHub} instance. + * + * @return the github + * @throws IOException + * the io exception + */ + public GitHub build() throws IOException { + return new GitHub(endpoint, + connector, + rateLimitHandler, + abuseLimitHandler, + rateLimitChecker, + authorizationProvider); + } + + /** + * Clone. * - * @param handler - * the handler * @return the GitHubBuilder - * @see #withRateLimitChecker(RateLimitChecker) */ - public GitHubBuilder withRateLimitHandler(GitHubRateLimitHandler handler) { - this.rateLimitHandler = handler; - return this; + @Override + public GitHubBuilder clone() { + try { + return (GitHubBuilder) super.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException("Clone should be supported", e); + } } } diff --git a/src/main/java/org/kohsuke/github/GitHubClient.java b/src/main/java/org/kohsuke/github/GitHubClient.java index ea2533cffa..38552b573c 100644 --- a/src/main/java/org/kohsuke/github/GitHubClient.java +++ b/src/main/java/org/kohsuke/github/GitHubClient.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.introspect.VisibilityChecker; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.apache.commons.io.IOUtils; import org.kohsuke.github.authorization.AuthorizationProvider; import org.kohsuke.github.authorization.UserAuthorizationProvider; @@ -50,659 +49,699 @@ */ class GitHubClient { - private static class GHApiInfo { - private String rateLimitUrl; + /** The Constant CONNECTION_ERROR_RETRIES. */ + private static final int DEFAULT_CONNECTION_ERROR_RETRIES = 2; - void check(String apiUrl) throws IOException { - if (rateLimitUrl == null) - throw new IOException(apiUrl + " doesn't look like GitHub API URL"); + /** The Constant DEFAULT_MINIMUM_RETRY_TIMEOUT_MILLIS. */ + private static final int DEFAULT_MINIMUM_RETRY_MILLIS = 100; - // make sure that the URL is legitimate - new URL(rateLimitUrl); - } - } + /** The Constant DEFAULT_MAXIMUM_RETRY_TIMEOUT_MILLIS. */ + private static final int DEFAULT_MAXIMUM_RETRY_MILLIS = DEFAULT_MINIMUM_RETRY_MILLIS; - /** - * Represents a supplier of results that can throw. - * - * @param - * the type of results supplied by this supplier - */ - @FunctionalInterface - interface BodyHandler extends FunctionThrows { - } + private static final ThreadLocal sendRequestTraceId = new ThreadLocal<>(); - /** - * The Class RetryRequestException. - */ - static class RetryRequestException extends IOException { + // Cache of myself object. + private final String apiUrl; - /** The connector request. */ - final GitHubConnectorRequest connectorRequest; + private final GitHubRateLimitHandler rateLimitHandler; + private final GitHubAbuseLimitHandler abuseLimitHandler; + private final GitHubRateLimitChecker rateLimitChecker; + private final AuthorizationProvider authorizationProvider; - /** - * Instantiates a new retry request exception. - */ - RetryRequestException() { - this(null); - } + private GitHubConnector connector; - /** - * Instantiates a new retry request exception. - * - * @param connectorRequest - * the connector request - */ - RetryRequestException(GitHubConnectorRequest connectorRequest) { - this.connectorRequest = connectorRequest; - } - } + @Nonnull + private final AtomicReference rateLimit = new AtomicReference<>(GHRateLimit.DEFAULT); - private static final DateTimeFormatter DATE_TIME_PARSER_SLASHES = DateTimeFormatter - .ofPattern("yyyy/MM/dd HH:mm:ss Z"); + @Nonnull + private final GitHubSanityCachedValue sanityCachedRateLimit = new GitHubSanityCachedValue<>(); - /** The Constant CONNECTION_ERROR_RETRIES. */ - private static final int DEFAULT_CONNECTION_ERROR_RETRIES = 2; + @Nonnull + private GitHubSanityCachedValue sanityCachedIsCredentialValid = new GitHubSanityCachedValue<>(); - /** The Constant DEFAULT_MAXIMUM_RETRY_TIMEOUT_MILLIS. */ - private static final int DEFAULT_MAXIMUM_RETRY_MILLIS = 100; - /** The Constant DEFAULT_MINIMUM_RETRY_TIMEOUT_MILLIS. */ - private static final int DEFAULT_MINIMUM_RETRY_MILLIS = DEFAULT_MAXIMUM_RETRY_MILLIS; private static final Logger LOGGER = Logger.getLogger(GitHubClient.class.getName()); - private static final ObjectMapper MAPPER = new ObjectMapper(); - private static final ThreadLocal sendRequestTraceId = new ThreadLocal<>(); + private static final ObjectMapper MAPPER = new ObjectMapper(); /** The Constant GITHUB_URL. */ static final String GITHUB_URL = "https://api.github.com"; + private static final DateTimeFormatter DATE_TIME_PARSER_SLASHES = DateTimeFormatter + .ofPattern("yyyy/MM/dd HH:mm:ss Z"); + static { - MAPPER.registerModule(new JavaTimeModule()); MAPPER.setVisibility(new VisibilityChecker.Std(NONE, NONE, NONE, NONE, ANY)); MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true); MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); } - @Nonnull - private static GitHubResponse createResponse(@Nonnull GitHubConnectorResponse connectorResponse, - @CheckForNull BodyHandler handler) throws IOException { - T body = null; - if (handler != null) { - if (!shouldIgnoreBody(connectorResponse)) { - body = handler.apply(connectorResponse); - } - } - return new GitHubResponse<>(connectorResponse, body); - } + /** + * Instantiates a new git hub client. + * + * @param apiUrl + * the api url + * @param connector + * the connector + * @param rateLimitHandler + * the rate limit handler + * @param abuseLimitHandler + * the abuse limit handler + * @param rateLimitChecker + * the rate limit checker + * @param authorizationProvider + * the authorization provider + * @throws IOException + * Signals that an I/O exception has occurred. + */ + GitHubClient(String apiUrl, + GitHubConnector connector, + GitHubRateLimitHandler rateLimitHandler, + GitHubAbuseLimitHandler abuseLimitHandler, + GitHubRateLimitChecker rateLimitChecker, + AuthorizationProvider authorizationProvider) throws IOException { - private static void detectOTPRequired(@Nonnull GitHubConnectorResponse connectorResponse) throws GHIOException { - // 401 Unauthorized == bad creds or OTP request - if (connectorResponse.statusCode() == HTTP_UNAUTHORIZED) { - // In the case of a user with 2fa enabled, a header with X-GitHub-OTP - // will be returned indicating the user needs to respond with an otp - if (connectorResponse.header("X-GitHub-OTP") != null) { - throw new GHOTPRequiredException().withResponseHeaderFields(connectorResponse.allHeaders()); - } + if (apiUrl.endsWith("/")) { + apiUrl = apiUrl.substring(0, apiUrl.length() - 1); // normalize } - } - // This implements the exact same rules as the ones applied in jdk.internal.net.http.RedirectFilter - private static String getRedirectedMethod(int statusCode, String originalMethod) { - switch (statusCode) { - case HTTP_MOVED_PERM : - case HTTP_MOVED_TEMP : - return originalMethod.equals("POST") ? "GET" : originalMethod; - case 303 : - return "GET"; - case 307 : - case 308 : - return originalMethod; - default : - return originalMethod; + if (null == connector) { + connector = GitHubConnector.DEFAULT; } - } + this.apiUrl = apiUrl; + this.connector = connector; - private static URI getRedirectedUri(URI requestUri, GitHubConnectorResponse connectorResponse) throws IOException { - URI redirectedURI; - redirectedURI = Optional.of(connectorResponse.header("Location")) - .map(URI::create) - .orElseThrow(() -> new IOException("Invalid redirection")); + // Prefer credential configuration via provider + this.authorizationProvider = authorizationProvider; - // redirect could be relative to original URL, but if not - // then redirect is used. - redirectedURI = requestUri.resolve(redirectedURI); - return redirectedURI; + this.rateLimitHandler = rateLimitHandler; + this.abuseLimitHandler = abuseLimitHandler; + this.rateLimitChecker = rateLimitChecker; } /** - * Handle API error by either throwing it or by returning normally to retry. + * Gets the login. + * + * @return the login */ - private static IOException interpretApiError(IOException e, - @Nonnull GitHubConnectorRequest connectorRequest, - @CheckForNull GitHubConnectorResponse connectorResponse) { - // If we're already throwing a GHIOException, pass through - if (e instanceof GHIOException) { - return e; - } - - int statusCode = -1; - String message = null; - Map> headers = new HashMap<>(); - String errorMessage = null; + String getLogin() { + try { + if (this.authorizationProvider instanceof UserAuthorizationProvider + && this.authorizationProvider.getEncodedAuthorization() != null) { - if (connectorResponse != null) { - statusCode = connectorResponse.statusCode(); - message = connectorResponse.header("Status"); - headers = connectorResponse.allHeaders(); - if (connectorResponse.statusCode() >= HTTP_BAD_REQUEST) { - errorMessage = GitHubResponse.getBodyAsStringOrNull(connectorResponse); - } - } + UserAuthorizationProvider userAuthorizationProvider = (UserAuthorizationProvider) this.authorizationProvider; - if (errorMessage != null) { - if (e instanceof FileNotFoundException) { - // pass through 404 Not Found to allow the caller to handle it intelligently - e = new GHFileNotFoundException(e.getMessage() + " " + errorMessage, e) - .withResponseHeaderFields(headers); - } else if (statusCode >= 0) { - e = new HttpException(errorMessage, statusCode, message, connectorRequest.url().toString(), e); - } else { - e = new GHIOException(errorMessage).withResponseHeaderFields(headers); + return userAuthorizationProvider.getLogin(); } - } else if (!(e instanceof FileNotFoundException)) { - e = new HttpException(statusCode, message, connectorRequest.url().toString(), e); + } catch (IOException e) { } - return e; + return null; } - // This implements the exact same rules as the ones applied in jdk.internal.net.http.RedirectFilter - private static boolean isRedirecting(int statusCode) { - return statusCode == HTTP_MOVED_PERM || statusCode == HTTP_MOVED_TEMP || statusCode == 303 || statusCode == 307 - || statusCode == 308; + private T fetch(Class type, String urlPath) throws IOException { + GitHubRequest request = GitHubRequest.newBuilder().withApiUrl(getApiUrl()).withUrlPath(urlPath).build(); + return sendRequest(request, (connectorResponse) -> GitHubResponse.parseBody(connectorResponse, type)).body(); } - private static void logRetryConnectionError(IOException e, URL url, int retries) throws IOException { - // There are a range of connection errors where we want to wait a moment and just automatically retry - - // WARNING: These are unsupported environment variables. - // The GitHubClient class is internal and may change at any time. - int minRetryInterval = Math.max(DEFAULT_MINIMUM_RETRY_MILLIS, - Integer.getInteger(GitHubClient.class.getName() + ".minRetryInterval", DEFAULT_MINIMUM_RETRY_MILLIS)); - int maxRetryInterval = Math.max(DEFAULT_MAXIMUM_RETRY_MILLIS, - Integer.getInteger(GitHubClient.class.getName() + ".maxRetryInterval", DEFAULT_MAXIMUM_RETRY_MILLIS)); - - long sleepTime = maxRetryInterval <= minRetryInterval - ? minRetryInterval - : ThreadLocalRandom.current().nextLong(minRetryInterval, maxRetryInterval); + /** + * Ensures that the credential for this client is valid. + * + * @return the boolean + */ + public boolean isCredentialValid() { + return sanityCachedIsCredentialValid.get(() -> { + try { + // If 404, ratelimit returns a default value. + // This works as credential test because invalid credentials returns 401, not 404 + getRateLimit(); + return Boolean.TRUE; + } catch (IOException e) { + LOGGER.log(FINE, + e, + () -> String.format("(%s) Exception validating credentials on %s with login '%s'", + sendRequestTraceId.get(), + getApiUrl(), + getLogin())); + return Boolean.FALSE; + } + }); + } - LOGGER.log(INFO, - () -> String.format( - "(%s) %s while connecting to %s: '%s'. Sleeping %d milliseconds before retrying (%d retries remaining)", - sendRequestTraceId.get(), - e.getClass().toString(), - url.toString(), - e.getMessage(), - sleepTime, - retries)); - try { - Thread.sleep(sleepTime); - } catch (InterruptedException ie) { - throw (IOException) new InterruptedIOException().initCause(e); - } + /** + * Is this an always offline "connection". + * + * @return {@code true} if this is an always offline "connection". + */ + public boolean isOffline() { + return connector == GitHubConnector.OFFLINE; } - private static GitHubConnectorRequest prepareConnectorRequest(GitHubRequest request, - AuthorizationProvider authorizationProvider) throws IOException { - GitHubRequest.Builder builder = request.toBuilder(); - // if the authentication is needed but no credential is given, try it anyway (so that some calls - // that do work with anonymous access in the reduced form should still work.) - if (!request.allHeaders().containsKey("Authorization")) { - String authorization = authorizationProvider.getEncodedAuthorization(); - if (authorization != null) { - builder.setHeader("Authorization", authorization); - } - } - if (request.header("Accept") == null) { - builder.setHeader("Accept", "application/vnd.github+json"); - } - builder.setHeader("Accept-Encoding", "gzip"); - - builder.setHeader("X-GitHub-Api-Version", "2022-11-28"); - - if (request.hasBody()) { - if (request.body() != null) { - builder.contentType(defaultString(request.contentType(), "application/x-www-form-urlencoded")); - } else { - builder.contentType("application/json"); - Map json = new HashMap<>(); - for (GitHubRequest.Entry e : request.args()) { - json.put(e.key, e.value); - } - builder.with(new ByteArrayInputStream(getMappingObjectWriter().writeValueAsBytes(json))); - } - - } - - return builder.build(); - } - - private static boolean shouldIgnoreBody(@Nonnull GitHubConnectorResponse connectorResponse) { - if (connectorResponse.statusCode() == HTTP_NOT_MODIFIED) { - // special case handling for 304 unmodified, as the content will be "" - return true; - } else if (connectorResponse.statusCode() == HTTP_ACCEPTED) { - - // Response code 202 means data is being generated or an action that can require some time is triggered. - // This happens in specific cases: - // statistics - See https://developer.github.com/v3/repos/statistics/#a-word-about-caching - // fork creation - See https://developer.github.com/v3/repos/forks/#create-a-fork - // workflow run cancellation - See https://docs.github.com/en/rest/reference/actions#cancel-a-workflow-run - - LOGGER.log(FINE, - () -> String.format("(%s) Received HTTP_ACCEPTED(202) from %s. Please try again in 5 seconds.", - sendRequestTraceId.get(), - connectorResponse.request().url().toString())); - return true; - } else { + /** + * Is this an anonymous connection. + * + * @return {@code true} if operations that require authentication will fail. + */ + public boolean isAnonymous() { + try { + return getLogin() == null && this.authorizationProvider.getEncodedAuthorization() == null; + } catch (IOException e) { + // An exception here means that the provider failed to provide authorization parameters, + // basically meaning the same as "no auth" return false; } } /** - * Helper for {@link #getMappingObjectReader(GitHubConnectorResponse)}. + * Gets the current full rate limit information from the server. * - * @param root - * the root GitHub object for this reader - * @return an {@link ObjectReader} instance that can be further configured. + * For some versions of GitHub Enterprise, the {@code /rate_limit} endpoint returns a {@code 404 Not Found}. In that + * case, the most recent {@link GHRateLimit} information will be returned, including rate limit information returned + * in the response header for this request in if was present. + * + * For most use cases it would be better to implement a {@link RateLimitChecker} and add it via + * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. + * + * @return the rate limit + * @throws IOException + * the io exception */ @Nonnull - static ObjectReader getMappingObjectReader(@Nonnull GitHub root) { - ObjectReader reader = getMappingObjectReader((GitHubConnectorResponse) null); - ((InjectableValues.Std) reader.getInjectableValues()).addValue(GitHub.class, root); - return reader; + public GHRateLimit getRateLimit() throws IOException { + return getRateLimit(RateLimitTarget.NONE); } /** - * Gets an {@link ObjectReader}. - * - * Members of {@link InjectableValues} must be present even if {@code null}, otherwise classes expecting those - * values will fail to read. This differs from regular JSONProperties which provide defaults instead of failing. - * - * Having one spot to create readers and having it take all injectable values is not a great long term solution but - * it is sufficient for this first cut. + * Gets the encoded authorization. * - * @param connectorResponse - * the {@link GitHubConnectorResponse} to inject for this reader. + * @return the encoded authorization + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @CheckForNull + String getEncodedAuthorization() throws IOException { + return authorizationProvider.getEncodedAuthorization(); + } + + /** + * Gets the rate limit. * - * @return an {@link ObjectReader} instance that can be further configured. + * @param rateLimitTarget + * the rate limit target + * @return the rate limit + * @throws IOException + * Signals that an I/O exception has occurred. */ @Nonnull - static ObjectReader getMappingObjectReader(@CheckForNull GitHubConnectorResponse connectorResponse) { - Map injected = new HashMap<>(); - - // Required or many things break - injected.put(GitHubConnectorResponse.class.getName(), null); - injected.put(GitHub.class.getName(), null); + GHRateLimit getRateLimit(@Nonnull RateLimitTarget rateLimitTarget) throws IOException { + // Even when explicitly asking for rate limit, restrict to sane query frequency + // return cached value if available + GHRateLimit output = sanityCachedRateLimit.get( + (currentValue) -> currentValue == null || currentValue.getRecord(rateLimitTarget).isExpired(), + () -> { + GHRateLimit result; + try { + final GitHubRequest request = GitHubRequest.newBuilder() + .rateLimit(RateLimitTarget.NONE) + .withApiUrl(getApiUrl()) + .withUrlPath("/rate_limit") + .build(); + result = this + .sendRequest(request, + (connectorResponse) -> GitHubResponse.parseBody(connectorResponse, + JsonRateLimit.class)) + .body().resources; + } catch (FileNotFoundException e) { + // For some versions of GitHub Enterprise, the rate_limit endpoint returns a 404. + LOGGER.log(FINE, "(%s) /rate_limit returned 404 Not Found.", sendRequestTraceId.get()); - if (connectorResponse != null) { - injected.put(GitHubConnectorResponse.class.getName(), connectorResponse); - GitHubConnectorRequest request = connectorResponse.request(); - // This is cheating, but it is an acceptable cheat for now. - if (request instanceof GitHubRequest) { - injected.putAll(((GitHubRequest) connectorResponse.request()).injectedMappingValues()); - } - } - return MAPPER.reader(new InjectableValues.Std(injected)); + // However some newer versions of GHE include rate limit header information + // If the header info is missing and the endpoint returns 404, fill the rate limit + // with unknown + result = GHRateLimit.fromRecord(GHRateLimit.UnknownLimitRecord.current(), rateLimitTarget); + } + return result; + }); + return updateRateLimit(output); } /** - * Gets an {@link ObjectWriter}. + * Returns the most recently observed rate limit data. * - * @return an {@link ObjectWriter} instance that can be further configured. + * Generally, instead of calling this you should implement a {@link RateLimitChecker} or call + * + * @return the most recently observed rate limit data. This may include expired or + * {@link GHRateLimit.UnknownLimitRecord} entries. + * @deprecated implement a {@link RateLimitChecker} and add it via + * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. */ @Nonnull - static ObjectWriter getMappingObjectWriter() { - return MAPPER.writer(); + @Deprecated + GHRateLimit lastRateLimit() { + return rateLimit.get(); } /** - * Parses the instant. + * Gets the current rate limit for an endpoint while trying not to actually make any remote requests unless + * absolutely necessary. * - * @param timestamp - * the timestamp - * @return the instant + * If the {@link GHRateLimit.Record} for {@code urlPath} is not expired, it is returned. If the + * {@link GHRateLimit.Record} for {@code urlPath} is expired, {@link #getRateLimit()} will be called to get the + * current rate limit. + * + * @param rateLimitTarget + * the endpoint to get the rate limit for. + * + * @return the current rate limit data. {@link GHRateLimit.Record}s in this instance may be expired when returned. + * @throws IOException + * if there was an error getting current rate limit data. */ - static Instant parseInstant(String timestamp) { - if (timestamp == null) - return null; - - if (timestamp.charAt(4) == '/') { - // Unsure where this is used, but retained for compatibility. - return Instant.from(DATE_TIME_PARSER_SLASHES.parse(timestamp)); - } else { - return Instant.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp)); + @Nonnull + GHRateLimit rateLimit(@Nonnull RateLimitTarget rateLimitTarget) throws IOException { + GHRateLimit result = rateLimit.get(); + // Most of the time rate limit is not expired, so try to avoid locking. + if (result.getRecord(rateLimitTarget).isExpired()) { + // if the rate limit is expired, synchronize to ensure + // only one call to getRateLimit() is made to refresh it. + synchronized (this) { + if (rateLimit.get().getRecord(rateLimitTarget).isExpired()) { + getRateLimit(rateLimitTarget); + } + } + result = rateLimit.get(); } + return result; } /** - * Parses the URL. + * Update the Rate Limit with the latest info from response header. * - * @param s - * the s - * @return the url + * Due to multi-threading, requests might complete out of order. This method calls + * {@link GHRateLimit#getMergedRateLimit(GHRateLimit)} to ensure the most current records are used. + * + * @param observed + * {@link GHRateLimit.Record} constructed from the response header information */ - static URL parseURL(String s) { - try { - return s == null ? null : new URL(s); - } catch (MalformedURLException e) { - throw new IllegalStateException("Invalid URL: " + s); - } + private GHRateLimit updateRateLimit(@Nonnull GHRateLimit observed) { + GHRateLimit result = rateLimit.accumulateAndGet(observed, (current, x) -> current.getMergedRateLimit(x)); + LOGGER.log(FINEST, "Rate limit now: {0}", rateLimit.get()); + return result; } /** - * Prints the instant. + * Tests the connection. * - * @param instant - * the instant - * @return the string + *

+ * Verify that the API URL and credentials are valid to access this GitHub. + * + *

+ * This method returns normally if the endpoint is reachable and verified to be GitHub API URL. Otherwise this + * method throws {@link IOException} to indicate the problem. + * + * @throws IOException + * the io exception */ - static String printInstant(Instant instant) { - return DateTimeFormatter.ISO_INSTANT.format(instant.truncatedTo(ChronoUnit.SECONDS)); + public void checkApiUrlValidity() throws IOException { + try { + this.fetch(GHApiInfo.class, "/").check(getApiUrl()); + } catch (IOException e) { + if (isPrivateModeEnabled()) { + throw (IOException) new IOException( + "GitHub Enterprise server (" + getApiUrl() + ") with private mode enabled").initCause(e); + } + throw e; + } } /** - * Convert Date to Instant or null. + * Gets the api url. * - * @param date - * the date - * @return the date + * @return the api url */ - static Instant toInstantOrNull(Date date) { - if (date == null) - return null; - - return date.toInstant(); + public String getApiUrl() { + return apiUrl; } /** - * Unmodifiable list or null. + * Builds a {@link GitHubRequest}, sends the {@link GitHubRequest} to the server, and uses the {@link BodyHandler} + * to parse the response info and response body data into an instance of {@link T}. * * @param - * the generic type - * @param list - * the list - * @return the list + * the type of the parse body data. + * @param builder + * used to build the request that will be sent to the server. + * @param handler + * parse the response info and body data into a instance of {@link T}. If null, no parsing occurs and + * {@link GitHubResponse#body()} will return null. + * @return a {@link GitHubResponse} containing the parsed body data as a {@link T}. Parsed instance may be null. + * @throws IOException + * if an I/O Exception occurs */ - static List unmodifiableListOrNull(List list) { - return list == null ? null : Collections.unmodifiableList(list); + @Nonnull + public GitHubResponse sendRequest(@Nonnull GitHubRequest.Builder builder, + @CheckForNull BodyHandler handler) throws IOException { + return sendRequest(builder.build(), handler); } /** - * Unmodifiable map or null. + * Sends the {@link GitHubRequest} to the server, and uses the {@link BodyHandler} to parse the response info and + * response body data into an instance of {@link T}. * - * @param - * the key type - * @param - * the value type - * @param map - * the map - * @return the map + * @param + * the type of the parse body data. + * @param request + * the request that will be sent to the server. + * @param handler + * parse the response info and body data into a instance of {@link T}. If null, no parsing occurs and + * {@link GitHubResponse#body()} will return null. + * @return a {@link GitHubResponse} containing the parsed body data as a {@link T}. Parsed instance may be null. + * @throws IOException + * if an I/O Exception occurs */ - static Map unmodifiableMapOrNull(Map map) { - return map == null ? null : Collections.unmodifiableMap(map); + @Nonnull + public GitHubResponse sendRequest(GitHubRequest request, @CheckForNull BodyHandler handler) + throws IOException { + // WARNING: This is an unsupported environment variable. + // The GitHubClient class is internal and may change at any time. + int retryCount = Math.max(DEFAULT_CONNECTION_ERROR_RETRIES, + Integer.getInteger(GitHubClient.class.getName() + ".retryCount", DEFAULT_CONNECTION_ERROR_RETRIES)); + + int retries = retryCount; + sendRequestTraceId.set(Integer.toHexString(request.hashCode())); + GitHubConnectorRequest connectorRequest = prepareConnectorRequest(request, authorizationProvider); + do { + GitHubConnectorResponse connectorResponse = null; + try { + logRequest(connectorRequest); + rateLimitChecker.checkRateLimit(this, request.rateLimitTarget()); + connectorResponse = connector.send(connectorRequest); + logResponse(connectorResponse); + noteRateLimit(request.rateLimitTarget(), connectorResponse); + detectKnownErrors(connectorResponse, request, handler != null); + logResponseBody(connectorResponse); + return createResponse(connectorResponse, handler); + } catch (RetryRequestException e) { + // retry requested by requested by error handler (rate limit handler for example) + if (retries > 0 && e.connectorRequest != null) { + connectorRequest = e.connectorRequest; + } + } catch (IOException e) { + throw interpretApiError(e, connectorRequest, connectorResponse); + } finally { + IOUtils.closeQuietly(connectorResponse); + } + } while (--retries >= 0); + + throw new GHIOException("Ran out of retries for URL: " + request.url().toString()); } - private final GitHubAbuseLimitHandler abuseLimitHandler; + private void detectKnownErrors(GitHubConnectorResponse connectorResponse, + GitHubRequest request, + boolean detectStatusCodeError) throws IOException { + detectOTPRequired(connectorResponse); + detectInvalidCached404Response(connectorResponse, request); + detectExpiredToken(connectorResponse, request); + detectRedirect(connectorResponse, request); + if (rateLimitHandler.isError(connectorResponse)) { + rateLimitHandler.onError(connectorResponse); + throw new RetryRequestException(); + } else if (abuseLimitHandler.isError(connectorResponse)) { + abuseLimitHandler.onError(connectorResponse); + throw new RetryRequestException(); + } else if (detectStatusCodeError + && GitHubConnectorResponseErrorHandler.STATUS_HTTP_BAD_REQUEST_OR_GREATER.isError(connectorResponse)) { + GitHubConnectorResponseErrorHandler.STATUS_HTTP_BAD_REQUEST_OR_GREATER.onError(connectorResponse); + } + } - // Cache of myself object. - private final String apiUrl; + private void detectExpiredToken(GitHubConnectorResponse connectorResponse, GitHubRequest request) + throws IOException { + if (connectorResponse.statusCode() != HTTP_UNAUTHORIZED) { + return; + } + String originalAuthorization = connectorResponse.request().header("Authorization"); + if (Objects.isNull(originalAuthorization) || originalAuthorization.isEmpty()) { + return; + } + GitHubConnectorRequest updatedRequest = prepareConnectorRequest(request, authorizationProvider); + String updatedAuthorization = updatedRequest.header("Authorization"); + if (!originalAuthorization.equals(updatedAuthorization)) { + throw new RetryRequestException(updatedRequest); + } + } - private final AuthorizationProvider authorizationProvider; + private void detectRedirect(GitHubConnectorResponse connectorResponse, GitHubRequest request) throws IOException { + if (isRedirecting(connectorResponse.statusCode())) { + // For redirects, GitHub expects the Authorization header to be removed. + // GitHubConnector implementations can follow any redirects automatically as long as they remove the header + // as well. + // Okhttp does this. + // https://github.com/square/okhttp/blob/f9dfd4e8cc070ca2875a67d8f7ad939d95e7e296/okhttp/src/main/kotlin/okhttp3/internal/http/RetryAndFollowUpInterceptor.kt#L313-L318 + // GitHubClient always strips Authorization from detected redirects for security. + // This problem was discovered when upload-artifact@v4 was released as the new + // service we are redirected to for downloading the artifacts doesn't support + // having the Authorization header set. + // See also https://github.com/arduino/report-size-deltas/pull/83 for more context - private GitHubConnector connector; + GitHubConnectorRequest updatedRequest = prepareRedirectRequest(connectorResponse, request); + throw new RetryRequestException(updatedRequest); + } + } - @Nonnull - private final AtomicReference rateLimit = new AtomicReference<>(GHRateLimit.DEFAULT); + private GitHubConnectorRequest prepareRedirectRequest(GitHubConnectorResponse connectorResponse, + GitHubRequest request) throws IOException { + URI requestUri = URI.create(request.url().toString()); + URI redirectedUri = getRedirectedUri(requestUri, connectorResponse); + // If we switch ports on the same host, we consider that as a different host + // This is slightly different from Redirect#NORMAL, but needed for local testing + boolean sameHost = redirectedUri.getHost().equalsIgnoreCase(request.url().getHost()) + && redirectedUri.getPort() == request.url().getPort(); - private final GitHubRateLimitChecker rateLimitChecker; + // mimicking the behavior of Redirect#NORMAL which was the behavior we used before + // Always redirect, except from HTTPS URLs to HTTP URLs. + if (!requestUri.getScheme().equalsIgnoreCase(redirectedUri.getScheme()) + && !"https".equalsIgnoreCase(redirectedUri.getScheme())) { + throw new HttpException("Attemped to redirect to a different scheme and the target scheme as not https.", + connectorResponse.statusCode(), + "Redirect", + connectorResponse.request().url().toString()); + } - private final GitHubRateLimitHandler rateLimitHandler; + String redirectedMethod = getRedirectedMethod(connectorResponse.statusCode(), request.method()); - @Nonnull - private GitHubSanityCachedValue sanityCachedIsCredentialValid = new GitHubSanityCachedValue<>(); + // let's build the new redirected request + GitHubRequest.Builder requestBuilder = request.toBuilder() + .setRawUrlPath(redirectedUri.toString()) + .method(redirectedMethod); + // if we redirect to a different host (even https), we remove the Authorization header + AuthorizationProvider provider = authorizationProvider; + if (!sameHost) { + requestBuilder.removeHeader("Authorization"); + provider = AuthorizationProvider.ANONYMOUS; + } + return prepareConnectorRequest(requestBuilder.build(), provider); + } - @Nonnull - private final GitHubSanityCachedValue sanityCachedRateLimit = new GitHubSanityCachedValue<>(); + private static URI getRedirectedUri(URI requestUri, GitHubConnectorResponse connectorResponse) throws IOException { + URI redirectedURI; + redirectedURI = Optional.of(connectorResponse.header("Location")) + .map(URI::create) + .orElseThrow(() -> new IOException("Invalid redirection")); - /** - * Instantiates a new git hub client. - * - * @param apiUrl - * the api url - * @param connector - * the connector - * @param rateLimitHandler - * the rate limit handler - * @param abuseLimitHandler - * the abuse limit handler - * @param rateLimitChecker - * the rate limit checker - * @param authorizationProvider - * the authorization provider - */ - GitHubClient(String apiUrl, - GitHubConnector connector, - GitHubRateLimitHandler rateLimitHandler, - GitHubAbuseLimitHandler abuseLimitHandler, - GitHubRateLimitChecker rateLimitChecker, - AuthorizationProvider authorizationProvider) { + // redirect could be relative to original URL, but if not + // then redirect is used. + redirectedURI = requestUri.resolve(redirectedURI); + return redirectedURI; + } - if (apiUrl.endsWith("/")) { - apiUrl = apiUrl.substring(0, apiUrl.length() - 1); // normalize - } + // This implements the exact same rules as the ones applied in jdk.internal.net.http.RedirectFilter + private static boolean isRedirecting(int statusCode) { + return statusCode == HTTP_MOVED_PERM || statusCode == HTTP_MOVED_TEMP || statusCode == 303 || statusCode == 307 + || statusCode == 308; + } - if (null == connector) { - connector = GitHubConnector.DEFAULT; + // This implements the exact same rules as the ones applied in jdk.internal.net.http.RedirectFilter + private static String getRedirectedMethod(int statusCode, String originalMethod) { + switch (statusCode) { + case HTTP_MOVED_PERM : + case HTTP_MOVED_TEMP : + return originalMethod.equals("POST") ? "GET" : originalMethod; + case 303 : + return "GET"; + case 307 : + case 308 : + return originalMethod; + default : + return originalMethod; } - this.apiUrl = apiUrl; - this.connector = connector; + } - // Prefer credential configuration via provider - this.authorizationProvider = authorizationProvider; + private static GitHubConnectorRequest prepareConnectorRequest(GitHubRequest request, + AuthorizationProvider authorizationProvider) throws IOException { + GitHubRequest.Builder builder = request.toBuilder(); + // if the authentication is needed but no credential is given, try it anyway (so that some calls + // that do work with anonymous access in the reduced form should still work.) + if (!request.allHeaders().containsKey("Authorization")) { + String authorization = authorizationProvider.getEncodedAuthorization(); + if (authorization != null) { + builder.setHeader("Authorization", authorization); + } + } + if (request.header("Accept") == null) { + builder.setHeader("Accept", "application/vnd.github+json"); + } + builder.setHeader("Accept-Encoding", "gzip"); - this.rateLimitHandler = rateLimitHandler; - this.abuseLimitHandler = abuseLimitHandler; - this.rateLimitChecker = rateLimitChecker; - } + builder.setHeader("X-GitHub-Api-Version", "2022-11-28"); - /** - * Tests the connection. - * - *

- * Verify that the API URL and credentials are valid to access this GitHub. - * - *

- * This method returns normally if the endpoint is reachable and verified to be GitHub API URL. Otherwise this - * method throws {@link IOException} to indicate the problem. - * - * @throws IOException - * the io exception - */ - public void checkApiUrlValidity() throws IOException { - try { - this.fetch(GHApiInfo.class, "/").check(getApiUrl()); - } catch (IOException e) { - if (isPrivateModeEnabled()) { - throw (IOException) new IOException( - "GitHub Enterprise server (" + getApiUrl() + ") with private mode enabled").initCause(e); + if (request.hasBody()) { + if (request.body() != null) { + builder.contentType(defaultString(request.contentType(), "application/x-www-form-urlencoded")); + } else { + builder.contentType("application/json"); + Map json = new HashMap<>(); + for (GitHubRequest.Entry e : request.args()) { + json.put(e.key, e.value); + } + builder.with(new ByteArrayInputStream(getMappingObjectWriter().writeValueAsBytes(json))); } - throw e; + } - } - /** - * Gets the api url. - * - * @return the api url - */ - public String getApiUrl() { - return apiUrl; + return builder.build(); } - /** - * Gets the current full rate limit information from the server. - * - * For some versions of GitHub Enterprise, the {@code /rate_limit} endpoint returns a {@code 404 Not Found}. In that - * case, the most recent {@link GHRateLimit} information will be returned, including rate limit information returned - * in the response header for this request in if was present. - * - * For most use cases it would be better to implement a {@link RateLimitChecker} and add it via - * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. - * - * @return the rate limit - * @throws IOException - * the io exception - */ - @Nonnull - public GHRateLimit getRateLimit() throws IOException { - return getRateLimit(RateLimitTarget.NONE); + private void logRequest(@Nonnull final GitHubConnectorRequest request) { + LOGGER.log(FINE, + () -> String.format("(%s) GitHub API request: %s %s", + sendRequestTraceId.get(), + request.method(), + request.url().toString())); } - /** - * Is this an anonymous connection. - * - * @return {@code true} if operations that require authentication will fail. - */ - public boolean isAnonymous() { - try { - return getLogin() == null && this.authorizationProvider.getEncodedAuthorization() == null; - } catch (IOException e) { - // An exception here means that the provider failed to provide authorization parameters, - // basically meaning the same as "no auth" - return false; - } + private void logResponse(@Nonnull final GitHubConnectorResponse response) { + LOGGER.log(FINER, () -> { + return String.format("(%s) GitHub API response: %s", + sendRequestTraceId.get(), + response.request().url().toString(), + response.statusCode()); + }); } - /** - * Ensures that the credential for this client is valid. - * - * @return the boolean - */ - public boolean isCredentialValid() { - return sanityCachedIsCredentialValid.get(() -> { + private void logResponseBody(@Nonnull final GitHubConnectorResponse response) { + LOGGER.log(FINEST, () -> { + String body; try { - // If 404, ratelimit returns a default value. - // This works as credential test because invalid credentials returns 401, not 404 - getRateLimit(); - return Boolean.TRUE; - } catch (IOException e) { - LOGGER.log(FINE, - e, - () -> String.format("(%s) Exception validating credentials on %s with login '%s'", - sendRequestTraceId.get(), - getApiUrl(), - getLogin())); - return Boolean.FALSE; + body = GitHubResponse.getBodyAsString(response); + } catch (Throwable e) { + body = "Error reading response body"; } + return String.format("(%s) GitHub API response body: %s", sendRequestTraceId.get(), body); + }); } + @Nonnull + private static GitHubResponse createResponse(@Nonnull GitHubConnectorResponse connectorResponse, + @CheckForNull BodyHandler handler) throws IOException { + T body = null; + if (handler != null) { + if (!shouldIgnoreBody(connectorResponse)) { + body = handler.apply(connectorResponse); + } + } + return new GitHubResponse<>(connectorResponse, body); + } + + private static boolean shouldIgnoreBody(@Nonnull GitHubConnectorResponse connectorResponse) { + if (connectorResponse.statusCode() == HTTP_NOT_MODIFIED) { + // special case handling for 304 unmodified, as the content will be "" + return true; + } else if (connectorResponse.statusCode() == HTTP_ACCEPTED) { + + // Response code 202 means data is being generated or an action that can require some time is triggered. + // This happens in specific cases: + // statistics - See https://developer.github.com/v3/repos/statistics/#a-word-about-caching + // fork creation - See https://developer.github.com/v3/repos/forks/#create-a-fork + // workflow run cancellation - See https://docs.github.com/en/rest/reference/actions#cancel-a-workflow-run + + LOGGER.log(FINE, + () -> String.format("(%s) Received HTTP_ACCEPTED(202) from %s. Please try again in 5 seconds.", + sendRequestTraceId.get(), + connectorResponse.request().url().toString())); + return true; + } else { + return false; + } + } + /** - * Is this an always offline "connection". - * - * @return {@code true} if this is an always offline "connection". + * Handle API error by either throwing it or by returning normally to retry. */ - public boolean isOffline() { - return connector == GitHubConnector.OFFLINE; - } + private static IOException interpretApiError(IOException e, + @Nonnull GitHubConnectorRequest connectorRequest, + @CheckForNull GitHubConnectorResponse connectorResponse) throws IOException { + // If we're already throwing a GHIOException, pass through + if (e instanceof GHIOException) { + return e; + } - /** - * Sends the {@link GitHubRequest} to the server, and uses the {@link BodyHandler} to parse the response info and - * response body data into an instance of {@code T}. - * - * @param - * the type of the parse body data. - * @param request - * the request that will be sent to the server. - * @param handler - * parse the response info and body data into a instance of {@code T}. If null, no parsing occurs and - * {@link GitHubResponse#body()} will return null. - * @return a {@link GitHubResponse} containing the parsed body data as a {@code T}. Parsed instance may be null. - * @throws IOException - * if an I/O Exception occurs - */ - @Nonnull - public GitHubResponse sendRequest(GitHubRequest request, @CheckForNull BodyHandler handler) - throws IOException { - // WARNING: This is an unsupported environment variable. - // The GitHubClient class is internal and may change at any time. - int retryCount = Math.max(DEFAULT_CONNECTION_ERROR_RETRIES, - Integer.getInteger(GitHubClient.class.getName() + ".retryCount", DEFAULT_CONNECTION_ERROR_RETRIES)); + int statusCode = -1; + String message = null; + Map> headers = new HashMap<>(); + String errorMessage = null; - int retries = retryCount; - sendRequestTraceId.set(Integer.toHexString(request.hashCode())); - GitHubConnectorRequest connectorRequest = prepareConnectorRequest(request, authorizationProvider); - do { - GitHubConnectorResponse connectorResponse = null; - try { - logRequest(connectorRequest); - rateLimitChecker.checkRateLimit(this, request.rateLimitTarget()); - connectorResponse = connector.send(connectorRequest); - logResponse(connectorResponse); - noteRateLimit(request.rateLimitTarget(), connectorResponse); - detectKnownErrors(connectorResponse, request, handler != null); - logResponseBody(connectorResponse); - return createResponse(connectorResponse, handler); - } catch (RetryRequestException e) { - // retry requested by requested by error handler (rate limit handler for example) - if (retries > 0 && e.connectorRequest != null) { - connectorRequest = e.connectorRequest; - } - } catch (IOException e) { - throw interpretApiError(e, connectorRequest, connectorResponse); - } finally { - IOUtils.closeQuietly(connectorResponse); + if (connectorResponse != null) { + statusCode = connectorResponse.statusCode(); + message = connectorResponse.header("Status"); + headers = connectorResponse.allHeaders(); + if (connectorResponse.statusCode() >= HTTP_BAD_REQUEST) { + errorMessage = GitHubResponse.getBodyAsStringOrNull(connectorResponse); } - } while (--retries >= 0); + } - throw new GHIOException("Ran out of retries for URL: " + request.url().toString()); + if (errorMessage != null) { + if (e instanceof FileNotFoundException) { + // pass through 404 Not Found to allow the caller to handle it intelligently + e = new GHFileNotFoundException(e.getMessage() + " " + errorMessage, e) + .withResponseHeaderFields(headers); + } else if (statusCode >= 0) { + e = new HttpException(errorMessage, statusCode, message, connectorRequest.url().toString(), e); + } else { + e = new GHIOException(errorMessage).withResponseHeaderFields(headers); + } + } else if (!(e instanceof FileNotFoundException)) { + e = new HttpException(statusCode, message, connectorRequest.url().toString(), e); + } + return e; } - /** - * Builds a {@link GitHubRequest}, sends the {@link GitHubRequest} to the server, and uses the {@link BodyHandler} - * to parse the response info and response body data into an instance of {@code T}. - * - * @param - * the type of the parse body data. - * @param builder - * used to build the request that will be sent to the server. - * @param handler - * parse the response info and body data into a instance of {@code T}. If null, no parsing occurs and - * {@link GitHubResponse#body()} will return null. - * @return a {@link GitHubResponse} containing the parsed body data as a {@code T}. Parsed instance may be null. - * @throws IOException - * if an I/O Exception occurs - */ - @Nonnull - public GitHubResponse sendRequest(@Nonnull GitHubRequest.Builder builder, - @CheckForNull BodyHandler handler) throws IOException { - return sendRequest(builder.build(), handler); - } + private static void logRetryConnectionError(IOException e, URL url, int retries) throws IOException { + // There are a range of connection errors where we want to wait a moment and just automatically retry - private void detectExpiredToken(GitHubConnectorResponse connectorResponse, GitHubRequest request) - throws IOException { - if (connectorResponse.statusCode() != HTTP_UNAUTHORIZED) { - return; - } - String originalAuthorization = connectorResponse.request().header("Authorization"); - if (Objects.isNull(originalAuthorization) || originalAuthorization.isEmpty()) { - return; - } - GitHubConnectorRequest updatedRequest = prepareConnectorRequest(request, authorizationProvider); - String updatedAuthorization = updatedRequest.header("Authorization"); - if (!originalAuthorization.equals(updatedAuthorization)) { - throw new RetryRequestException(updatedRequest); + // WARNING: These are unsupported environment variables. + // The GitHubClient class is internal and may change at any time. + int minRetryInterval = Math.max(DEFAULT_MINIMUM_RETRY_MILLIS, + Integer.getInteger(GitHubClient.class.getName() + ".minRetryInterval", DEFAULT_MINIMUM_RETRY_MILLIS)); + int maxRetryInterval = Math.max(DEFAULT_MAXIMUM_RETRY_MILLIS, + Integer.getInteger(GitHubClient.class.getName() + ".maxRetryInterval", DEFAULT_MAXIMUM_RETRY_MILLIS)); + + long sleepTime = maxRetryInterval <= minRetryInterval + ? minRetryInterval + : ThreadLocalRandom.current().nextLong(minRetryInterval, maxRetryInterval); + + LOGGER.log(INFO, + () -> String.format( + "(%s) %s while connecting to %s: '%s'. Sleeping %d milliseconds before retrying (%d retries remaining)", + sendRequestTraceId.get(), + e.getClass().toString(), + url.toString(), + e.getMessage(), + sleepTime, + retries)); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException ie) { + throw (IOException) new InterruptedIOException().initCause(e); } } @@ -735,46 +774,52 @@ private void detectInvalidCached404Response(GitHubConnectorResponse connectorRes } } - private void detectKnownErrors(GitHubConnectorResponse connectorResponse, - GitHubRequest request, - boolean detectStatusCodeError) throws IOException { - detectOTPRequired(connectorResponse); - detectInvalidCached404Response(connectorResponse, request); - detectExpiredToken(connectorResponse, request); - detectRedirect(connectorResponse, request); - if (rateLimitHandler.isError(connectorResponse)) { - rateLimitHandler.onError(connectorResponse); - throw new RetryRequestException(); - } else if (abuseLimitHandler.isError(connectorResponse)) { - abuseLimitHandler.onError(connectorResponse); - throw new RetryRequestException(); - } else if (detectStatusCodeError - && GitHubConnectorResponseErrorHandler.STATUS_HTTP_BAD_REQUEST_OR_GREATER.isError(connectorResponse)) { - GitHubConnectorResponseErrorHandler.STATUS_HTTP_BAD_REQUEST_OR_GREATER.onError(connectorResponse); + private void noteRateLimit(@Nonnull RateLimitTarget rateLimitTarget, + @Nonnull GitHubConnectorResponse connectorResponse) { + try { + int limit = connectorResponse.parseInt("X-RateLimit-Limit"); + int remaining = connectorResponse.parseInt("X-RateLimit-Remaining"); + int reset = connectorResponse.parseInt("X-RateLimit-Reset"); + GHRateLimit.Record observed = new GHRateLimit.Record(limit, remaining, reset, connectorResponse); + updateRateLimit(GHRateLimit.fromRecord(observed, rateLimitTarget)); + } catch (NumberFormatException e) { + LOGGER.log(FINER, + () -> String.format("(%s) Missing or malformed X-RateLimit header: %s", + sendRequestTraceId.get(), + e.getMessage())); } } - private void detectRedirect(GitHubConnectorResponse connectorResponse, GitHubRequest request) throws IOException { - if (isRedirecting(connectorResponse.statusCode())) { - // For redirects, GitHub expects the Authorization header to be removed. - // GitHubConnector implementations can follow any redirects automatically as long as they remove the header - // as well. - // Okhttp does this. - // https://github.com/square/okhttp/blob/f9dfd4e8cc070ca2875a67d8f7ad939d95e7e296/okhttp/src/main/kotlin/okhttp3/internal/http/RetryAndFollowUpInterceptor.kt#L313-L318 - // GitHubClient always strips Authorization from detected redirects for security. - // This problem was discovered when upload-artifact@v4 was released as the new - // service we are redirected to for downloading the artifacts doesn't support - // having the Authorization header set. - // See also https://github.com/arduino/report-size-deltas/pull/83 for more context - - GitHubConnectorRequest updatedRequest = prepareRedirectRequest(connectorResponse, request); - throw new RetryRequestException(updatedRequest); + private static void detectOTPRequired(@Nonnull GitHubConnectorResponse connectorResponse) throws GHIOException { + // 401 Unauthorized == bad creds or OTP request + if (connectorResponse.statusCode() == HTTP_UNAUTHORIZED) { + // In the case of a user with 2fa enabled, a header with X-GitHub-OTP + // will be returned indicating the user needs to respond with an otp + if (connectorResponse.header("X-GitHub-OTP") != null) { + throw new GHOTPRequiredException().withResponseHeaderFields(connectorResponse.allHeaders()); + } } } - private T fetch(Class type, String urlPath) throws IOException { - GitHubRequest request = GitHubRequest.newBuilder().withApiUrl(getApiUrl()).withUrlPath(urlPath).build(); - return sendRequest(request, (connectorResponse) -> GitHubResponse.parseBody(connectorResponse, type)).body(); + /** + * Require credential. + */ + void requireCredential() { + if (isAnonymous()) + throw new IllegalStateException( + "This operation requires a credential but none is given to the GitHub constructor"); + } + + private static class GHApiInfo { + private String rate_limit_url; + + void check(String apiUrl) throws IOException { + if (rate_limit_url == null) + throw new IOException(apiUrl + " doesn't look like GitHub API URL"); + + // make sure that the URL is legitimate + new URL(rate_limit_url); + } } /** @@ -814,229 +859,183 @@ private boolean isPrivateModeEnabled() { } } - private void logRequest(@Nonnull final GitHubConnectorRequest request) { - LOGGER.log(FINE, - () -> String.format("(%s) GitHub API request: %s %s", - sendRequestTraceId.get(), - request.method(), - request.url().toString())); - } - - private void logResponse(@Nonnull final GitHubConnectorResponse response) { - LOGGER.log(FINER, () -> { - return String.format("(%s) GitHub API response: %s", - sendRequestTraceId.get(), - response.request().url().toString(), - response.statusCode()); - }); - } - - private void logResponseBody(@Nonnull final GitHubConnectorResponse response) { - LOGGER.log(FINEST, () -> { - String body; - try { - response.setBodyStreamRereadable(); - body = GitHubResponse.getBodyAsString(response); - } catch (Throwable e) { - body = "Error reading response body"; - } - return String.format("(%s) GitHub API response body: %s", sendRequestTraceId.get(), body); - - }); - } - - private void noteRateLimit(@Nonnull RateLimitTarget rateLimitTarget, - @Nonnull GitHubConnectorResponse connectorResponse) { - try { - int limit = connectorResponse.parseInt("X-RateLimit-Limit"); - int remaining = connectorResponse.parseInt("X-RateLimit-Remaining"); - int reset = connectorResponse.parseInt("X-RateLimit-Reset"); - GHRateLimit.Record observed = new GHRateLimit.Record(limit, remaining, reset, connectorResponse); - updateRateLimit(GHRateLimit.fromRecord(observed, rateLimitTarget)); - } catch (NumberFormatException e) { - LOGGER.log(FINER, - () -> String.format("(%s) Missing or malformed X-RateLimit header: %s", - sendRequestTraceId.get(), - e.getMessage())); + /** + * Parses the URL. + * + * @param s + * the s + * @return the url + */ + static URL parseURL(String s) { + try { + return s == null ? null : new URL(s); + } catch (MalformedURLException e) { + throw new IllegalStateException("Invalid URL: " + s); } } - private GitHubConnectorRequest prepareRedirectRequest(GitHubConnectorResponse connectorResponse, - GitHubRequest request) throws IOException { - URI requestUri = URI.create(request.url().toString()); - URI redirectedUri = getRedirectedUri(requestUri, connectorResponse); - // If we switch ports on the same host, we consider that as a different host - // This is slightly different from Redirect#NORMAL, but needed for local testing - boolean sameHost = redirectedUri.getHost().equalsIgnoreCase(request.url().getHost()) - && redirectedUri.getPort() == request.url().getPort(); + /** + * Parses the date. + * + * @param timestamp + * the timestamp + * @return the date + */ + static Date parseDate(String timestamp) { + if (timestamp == null) + return null; - // mimicking the behavior of Redirect#NORMAL which was the behavior we used before - // Always redirect, except from HTTPS URLs to HTTP URLs. - if (!requestUri.getScheme().equalsIgnoreCase(redirectedUri.getScheme()) - && !"https".equalsIgnoreCase(redirectedUri.getScheme())) { - throw new HttpException("Attemped to redirect to a different scheme and the target scheme as not https.", - connectorResponse.statusCode(), - "Redirect", - connectorResponse.request().url().toString()); - } + return Date.from(parseInstant(timestamp)); + } - String redirectedMethod = getRedirectedMethod(connectorResponse.statusCode(), request.method()); + /** + * Parses the instant. + * + * @param timestamp + * the timestamp + * @return the instant + */ + static Instant parseInstant(String timestamp) { + if (timestamp == null) + return null; - // let's build the new redirected request - GitHubRequest.Builder requestBuilder = request.toBuilder() - .setRawUrlPath(redirectedUri.toString()) - .method(redirectedMethod); - // if we redirect to a different host (even https), we remove the Authorization header - AuthorizationProvider provider = authorizationProvider; - if (!sameHost) { - requestBuilder.removeHeader("Authorization"); - provider = AuthorizationProvider.ANONYMOUS; + if (timestamp.charAt(4) == '/') { + // Unsure where this is used, but retained for compatibility. + return Instant.from(DATE_TIME_PARSER_SLASHES.parse(timestamp)); + } else { + return Instant.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp)); } - return prepareConnectorRequest(requestBuilder.build(), provider); } /** - * Update the Rate Limit with the latest info from response header. + * Prints the date. * - * Due to multi-threading, requests might complete out of order. This method calls - * {@link GHRateLimit#getMergedRateLimit(GHRateLimit)} to ensure the most current records are used. + * @param dt + * the dt + * @return the string + */ + static String printDate(Date dt) { + return DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochMilli(dt.getTime()).truncatedTo(ChronoUnit.SECONDS)); + } + + /** + * Gets an {@link ObjectWriter}. * - * @param observed - * {@link GHRateLimit.Record} constructed from the response header information + * @return an {@link ObjectWriter} instance that can be further configured. */ - private GHRateLimit updateRateLimit(@Nonnull GHRateLimit observed) { - GHRateLimit result = rateLimit.accumulateAndGet(observed, (current, x) -> current.getMergedRateLimit(x)); - LOGGER.log(FINEST, "Rate limit now: {0}", rateLimit.get()); - return result; + @Nonnull + static ObjectWriter getMappingObjectWriter() { + return MAPPER.writer(); } /** - * Gets the encoded authorization. + * Helper for {@link #getMappingObjectReader(GitHubConnectorResponse)}. * - * @return the encoded authorization - * @throws IOException - * Signals that an I/O exception has occurred. + * @param root + * the root GitHub object for this reader + * @return an {@link ObjectReader} instance that can be further configured. */ - @CheckForNull - String getEncodedAuthorization() throws IOException { - return authorizationProvider.getEncodedAuthorization(); + @Nonnull + static ObjectReader getMappingObjectReader(@Nonnull GitHub root) { + ObjectReader reader = getMappingObjectReader((GitHubConnectorResponse) null); + ((InjectableValues.Std) reader.getInjectableValues()).addValue(GitHub.class, root); + return reader; } /** - * Gets the login. + * Gets an {@link ObjectReader}. * - * @return the login + * Members of {@link InjectableValues} must be present even if {@code null}, otherwise classes expecting those + * values will fail to read. This differs from regular JSONProperties which provide defaults instead of failing. + * + * Having one spot to create readers and having it take all injectable values is not a great long term solution but + * it is sufficient for this first cut. + * + * @param connectorResponse + * the {@link GitHubConnectorResponse} to inject for this reader. + * + * @return an {@link ObjectReader} instance that can be further configured. */ - String getLogin() { - try { - if (this.authorizationProvider instanceof UserAuthorizationProvider - && this.authorizationProvider.getEncodedAuthorization() != null) { + @Nonnull + static ObjectReader getMappingObjectReader(@CheckForNull GitHubConnectorResponse connectorResponse) { + Map injected = new HashMap<>(); - UserAuthorizationProvider userAuthorizationProvider = (UserAuthorizationProvider) this.authorizationProvider; + // Required or many things break + injected.put(GitHubConnectorResponse.class.getName(), null); + injected.put(GitHub.class.getName(), null); - return userAuthorizationProvider.getLogin(); + if (connectorResponse != null) { + injected.put(GitHubConnectorResponse.class.getName(), connectorResponse); + GitHubConnectorRequest request = connectorResponse.request(); + // This is cheating, but it is an acceptable cheat for now. + if (request instanceof GitHubRequest) { + injected.putAll(((GitHubRequest) connectorResponse.request()).injectedMappingValues()); } - } catch (IOException e) { } - return null; + return MAPPER.reader(new InjectableValues.Std(injected)); } /** - * Gets the rate limit. + * Unmodifiable map or null. * - * @param rateLimitTarget - * the rate limit target - * @return the rate limit - * @throws IOException - * Signals that an I/O exception has occurred. + * @param + * the key type + * @param + * the value type + * @param map + * the map + * @return the map */ - @Nonnull - GHRateLimit getRateLimit(@Nonnull RateLimitTarget rateLimitTarget) throws IOException { - // Even when explicitly asking for rate limit, restrict to sane query frequency - // return cached value if available - GHRateLimit output = sanityCachedRateLimit.get( - (currentValue) -> currentValue == null || currentValue.getRecord(rateLimitTarget).isExpired(), - () -> { - GHRateLimit result; - try { - final GitHubRequest request = GitHubRequest.newBuilder() - .rateLimit(RateLimitTarget.NONE) - .withApiUrl(getApiUrl()) - .withUrlPath("/rate_limit") - .build(); - result = this - .sendRequest(request, - (connectorResponse) -> GitHubResponse.parseBody(connectorResponse, - JsonRateLimit.class)) - .body().resources; - } catch (FileNotFoundException e) { - // For some versions of GitHub Enterprise, the rate_limit endpoint returns a 404. - LOGGER.log(FINE, "(%s) /rate_limit returned 404 Not Found.", sendRequestTraceId.get()); - - // However some newer versions of GHE include rate limit header information - // If the header info is missing and the endpoint returns 404, fill the rate limit - // with unknown - result = GHRateLimit.fromRecord(GHRateLimit.UnknownLimitRecord.current(), rateLimitTarget); - } - return result; - }); - return updateRateLimit(output); + static Map unmodifiableMapOrNull(Map map) { + return map == null ? null : Collections.unmodifiableMap(map); } /** - * Returns the most recently observed rate limit data. - * - * Generally, instead of calling this you should implement a {@link RateLimitChecker} or call + * Unmodifiable list or null. * - * @return the most recently observed rate limit data. This may include expired or - * {@link GHRateLimit.UnknownLimitRecord} entries. - * @deprecated implement a {@link RateLimitChecker} and add it via - * {@link GitHubBuilder#withRateLimitChecker(RateLimitChecker)}. + * @param + * the generic type + * @param list + * the list + * @return the list */ - @Nonnull - @Deprecated - GHRateLimit lastRateLimit() { - return rateLimit.get(); + static List unmodifiableListOrNull(List list) { + return list == null ? null : Collections.unmodifiableList(list); } /** - * Gets the current rate limit for an endpoint while trying not to actually make any remote requests unless - * absolutely necessary. - * - * If the {@link GHRateLimit.Record} for {@code urlPath} is not expired, it is returned. If the - * {@link GHRateLimit.Record} for {@code urlPath} is expired, {@link #getRateLimit()} will be called to get the - * current rate limit. - * - * @param rateLimitTarget - * the endpoint to get the rate limit for. - * - * @return the current rate limit data. {@link GHRateLimit.Record}s in this instance may be expired when returned. - * @throws IOException - * if there was an error getting current rate limit data. + * The Class RetryRequestException. */ - @Nonnull - GHRateLimit rateLimit(@Nonnull RateLimitTarget rateLimitTarget) throws IOException { - GHRateLimit result = rateLimit.get(); - // Most of the time rate limit is not expired, so try to avoid locking. - if (result.getRecord(rateLimitTarget).isExpired()) { - // if the rate limit is expired, synchronize to ensure - // only one call to getRateLimit() is made to refresh it. - synchronized (this) { - if (rateLimit.get().getRecord(rateLimitTarget).isExpired()) { - getRateLimit(rateLimitTarget); - } - } - result = rateLimit.get(); + static class RetryRequestException extends IOException { + + /** The connector request. */ + final GitHubConnectorRequest connectorRequest; + + /** + * Instantiates a new retry request exception. + */ + RetryRequestException() { + this(null); + } + + /** + * Instantiates a new retry request exception. + * + * @param connectorRequest + * the connector request + */ + RetryRequestException(GitHubConnectorRequest connectorRequest) { + this.connectorRequest = connectorRequest; } - return result; } /** - * Require credential. + * Represents a supplier of results that can throw. + * + * @param + * the type of results supplied by this supplier */ - void requireCredential() { - if (isAnonymous()) - throw new IllegalStateException( - "This operation requires a credential but none is given to the GitHub constructor"); + @FunctionalInterface + interface BodyHandler extends FunctionThrows { } } diff --git a/src/main/java/org/kohsuke/github/GitHubConnectorResponseErrorHandler.java b/src/main/java/org/kohsuke/github/GitHubConnectorResponseErrorHandler.java index cb729e321c..0a7f7fa9fb 100644 --- a/src/main/java/org/kohsuke/github/GitHubConnectorResponseErrorHandler.java +++ b/src/main/java/org/kohsuke/github/GitHubConnectorResponseErrorHandler.java @@ -34,6 +34,34 @@ abstract class GitHubConnectorResponseErrorHandler { */ public static final int TOO_MANY_REQUESTS = 429; + /** + * Called to detect an error handled by this handler. + * + * @param connectorResponse + * the connector response + * @return {@code true} if there is an error and {@link #onError(GitHubConnectorResponse)} should be called + * @throws IOException + * Signals that an I/O exception has occurred. + */ + abstract boolean isError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException; + + /** + * Called when the library encounters HTTP error matching {@link #isError(GitHubConnectorResponse)} + * + *

+ * Any exception thrown from this method will cause the request to fail, and the caller of github-api will receive + * an exception. If this method returns normally, another request will be attempted. For that to make sense, the + * implementation needs to wait for some time. + * + * @param connectorResponse + * Response information for this request. + * + * @throws IOException + * the io exception + * @see API documentation from GitHub + */ + public abstract void onError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException; + /** The status http bad request or greater. */ static GitHubConnectorResponseErrorHandler STATUS_HTTP_BAD_REQUEST_OR_GREATER = new GitHubConnectorResponseErrorHandler() { private static final String CONTENT_TYPE = "Content-type"; @@ -83,32 +111,4 @@ private boolean isServiceDown(GitHubConnectorResponse connectorResponse) throws return false; } }; - - /** - * Called when the library encounters HTTP error matching {@link #isError(GitHubConnectorResponse)} - * - *

- * Any exception thrown from this method will cause the request to fail, and the caller of github-api will receive - * an exception. If this method returns normally, another request will be attempted. For that to make sense, the - * implementation needs to wait for some time. - * - * @param connectorResponse - * Response information for this request. - * - * @throws IOException - * the io exception - * @see API documentation from GitHub - */ - public abstract void onError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException; - - /** - * Called to detect an error handled by this handler. - * - * @param connectorResponse - * the connector response - * @return {@code true} if there is an error and {@link #onError(GitHubConnectorResponse)} should be called - * @throws IOException - * Signals that an I/O exception has occurred. - */ - abstract boolean isError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException; } diff --git a/src/main/java/org/kohsuke/github/GitHubInteractiveObject.java b/src/main/java/org/kohsuke/github/GitHubInteractiveObject.java index d1a8aebdc7..a34f6485e7 100644 --- a/src/main/java/org/kohsuke/github/GitHubInteractiveObject.java +++ b/src/main/java/org/kohsuke/github/GitHubInteractiveObject.java @@ -15,7 +15,7 @@ * * @author Liam Newman */ -abstract class GitHubInteractiveObject extends GitHubBridgeAdapterObject { +abstract class GitHubInteractiveObject { @JacksonInject @CheckForNull private transient final GitHub root; @@ -38,21 +38,22 @@ abstract class GitHubInteractiveObject extends GitHubBridgeAdapterObject { } /** - * Object is offline. + * Get the root {@link GitHub} instance for this object. * - * @return true if GitHub instance is null or offline. + * @return the root {@link GitHub} instance */ - boolean isOffline() { - return root == null || root.isOffline(); + @NonNull + GitHub root() { + return Objects.requireNonNull(root, + "The root GitHub reference for this instance is null. Probably caused by deserializing this class without using a GitHub instance. If you must do this, use the MappingObjectReader from GitHub.getMappingObjectReader()."); } /** - * Get the root {@link GitHub} instance for this object. + * Object is offline. * - * @return the root {@link GitHub} instance + * @return true if GitHub instance is null or offline. */ - @NonNull GitHub root() { - return Objects.requireNonNull(root, - "The root GitHub reference for this instance is null. Probably caused by deserializing this class without using a GitHub instance. If you must do this, use the MappingObjectReader from GitHub.getMappingObjectReader()."); + boolean isOffline() { + return root == null || root.isOffline(); } } diff --git a/src/main/java/org/kohsuke/github/GitHubPageContentsIterable.java b/src/main/java/org/kohsuke/github/GitHubPageContentsIterable.java index f8fc7e4907..0af3fe96c7 100644 --- a/src/main/java/org/kohsuke/github/GitHubPageContentsIterable.java +++ b/src/main/java/org/kohsuke/github/GitHubPageContentsIterable.java @@ -19,29 +19,10 @@ */ class GitHubPageContentsIterable extends PagedIterable { - /** - * This class is not thread-safe. Any one instance should only be called from a single thread. - */ - private class GitHubPageContentsIterator extends PagedIterator { - - public GitHubPageContentsIterator(GitHubPageIterator iterator, Consumer itemInitializer) { - super(iterator, itemInitializer); - } - - /** - * Gets the {@link GitHubResponse} for the last page received. - * - * @return the {@link GitHubResponse} for the last page received. - */ - private GitHubResponse lastResponse() { - return ((GitHubPageIterator) base).finalResponse(); - } - } - private final GitHubClient client; - private final Consumer itemInitializer; - private final Class receiverType; private final GitHubRequest request; + private final Class receiverType; + private final Consumer itemInitializer; /** * Instantiates a new git hub page contents iterable. @@ -76,7 +57,7 @@ public PagedIterator _iterator(int pageSize) { } /** - * Eagerly walk {@link Iterable} and return the result in a {@link GitHubResponse} containing an array of {@code T} + * Eagerly walk {@link Iterable} and return the result in a {@link GitHubResponse} containing an array of {@link T} * items. * * @return the last response with an array containing all the results from all pages. @@ -90,4 +71,23 @@ GitHubResponse toResponse() throws IOException { GitHubResponse lastResponse = iterator.lastResponse(); return new GitHubResponse<>(lastResponse, items); } + + /** + * This class is not thread-safe. Any one instance should only be called from a single thread. + */ + private class GitHubPageContentsIterator extends PagedIterator { + + public GitHubPageContentsIterator(GitHubPageIterator iterator, Consumer itemInitializer) { + super(iterator, itemInitializer); + } + + /** + * Gets the {@link GitHubResponse} for the last page received. + * + * @return the {@link GitHubResponse} for the last page received. + */ + private GitHubResponse lastResponse() { + return ((GitHubPageIterator) base).finalResponse(); + } + } } diff --git a/src/main/java/org/kohsuke/github/GitHubPageIterator.java b/src/main/java/org/kohsuke/github/GitHubPageIterator.java index 4a831bf3f8..4f622d05b4 100644 --- a/src/main/java/org/kohsuke/github/GitHubPageIterator.java +++ b/src/main/java/org/kohsuke/github/GitHubPageIterator.java @@ -1,6 +1,7 @@ package org.kohsuke.github; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; import java.util.Iterator; import java.util.NoSuchElementException; @@ -9,9 +10,9 @@ // TODO: Auto-generated Javadoc /** - * May be used for any item that has pagination information. Iterates over paginated {@code T} objects (not the items - * inside the page). Also exposes {@link #finalResponse()} to allow getting a full {@link GitHubResponse}{@code } - * after iterating completes. + * May be used for any item that has pagination information. Iterates over paginated {@link T} objects (not the items + * inside the page). Also exposes {@link #finalResponse()} to allow getting a full {@link GitHubResponse} after + * iterating completes. * * Works for array responses, also works for search results which are single instances with an array of items inside. * @@ -23,41 +24,8 @@ */ class GitHubPageIterator implements Iterator { - /** - * Loads paginated resources. - * - * @param - * type of each page (not the items in the page). - * @param client - * the {@link GitHubClient} from which to request responses - * @param type - * type of each page (not the items in the page). - * @param request - * the request - * @param pageSize - * the page size - * @return iterator - */ - static GitHubPageIterator create(GitHubClient client, Class type, GitHubRequest request, int pageSize) { - - if (pageSize > 0) { - GitHubRequest.Builder builder = request.toBuilder().with("per_page", pageSize); - request = builder.build(); - } - - if (!"GET".equals(request.method())) { - throw new IllegalArgumentException("Request method \"GET\" is required for page iterator."); - } - - return new GitHubPageIterator<>(client, type, request); - } private final GitHubClient client; - - /** - * When done iterating over pages, it is on rare occasions useful to be able to get information from the final - * response that was retrieved. - */ - private GitHubResponse finalResponse = null; + private final Class type; /** * The page that will be returned when {@link #next()} is called. @@ -77,7 +45,11 @@ static GitHubPageIterator create(GitHubClient client, Class type, GitH */ private GitHubRequest nextRequest; - private final Class type; + /** + * When done iterating over pages, it is on rare occasions useful to be able to get information from the final + * response that was retrieved. + */ + private GitHubResponse finalResponse = null; private GitHubPageIterator(GitHubClient client, Class type, GitHubRequest request) { this.client = client; @@ -86,15 +58,32 @@ private GitHubPageIterator(GitHubClient client, Class type, GitHubRequest req } /** - * On rare occasions the final response from iterating is needed. + * Loads paginated resources. * - * @return the final response of the iterator. + * @param + * type of each page (not the items in the page). + * @param client + * the {@link GitHubClient} from which to request responses + * @param type + * type of each page (not the items in the page). + * @param request + * the request + * @param pageSize + * the page size + * @return iterator */ - public GitHubResponse finalResponse() { - if (hasNext()) { - throw new GHException("Final response is not available until after iterator is done."); + static GitHubPageIterator create(GitHubClient client, Class type, GitHubRequest request, int pageSize) { + + if (pageSize > 0) { + GitHubRequest.Builder builder = request.toBuilder().with("per_page", pageSize); + request = builder.build(); } - return finalResponse; + + if (!"GET".equals(request.method())) { + throw new IllegalArgumentException("Request method \"GET\" is required for page iterator."); + } + + return new GitHubPageIterator<>(client, type, request); } /** @@ -121,6 +110,18 @@ public T next() { return result; } + /** + * On rare occasions the final response from iterating is needed. + * + * @return the final response of the iterator. + */ + public GitHubResponse finalResponse() { + if (hasNext()) { + throw new GHException("Final response is not available until after iterator is done."); + } + return finalResponse; + } + /** * Fetch is called at the start of {@link #hasNext()} or {@link #next()} to fetch another page of data if it is * needed. @@ -160,7 +161,8 @@ private void fetch() { /** * Locate the next page from the pagination "Link" tag. */ - private GitHubRequest findNextURL(GitHubRequest nextRequest, GitHubResponse nextResponse) { + private GitHubRequest findNextURL(GitHubRequest nextRequest, GitHubResponse nextResponse) + throws MalformedURLException { GitHubRequest result = null; String link = nextResponse.header("Link"); if (link != null) { diff --git a/src/main/java/org/kohsuke/github/GitHubRateLimitChecker.java b/src/main/java/org/kohsuke/github/GitHubRateLimitChecker.java index 00ab62ef8b..576cd6a660 100644 --- a/src/main/java/org/kohsuke/github/GitHubRateLimitChecker.java +++ b/src/main/java/org/kohsuke/github/GitHubRateLimitChecker.java @@ -32,19 +32,19 @@ */ class GitHubRateLimitChecker { - private static final Logger LOGGER = Logger.getLogger(GitHubRateLimitChecker.class.getName()); - @Nonnull private final RateLimitChecker core; + @Nonnull + private final RateLimitChecker search; + @Nonnull private final RateLimitChecker graphql; @Nonnull private final RateLimitChecker integrationManifest; - @Nonnull - private final RateLimitChecker search; + private static final Logger LOGGER = Logger.getLogger(GitHubRateLimitChecker.class.getName()); /** * Instantiates a new git hub rate limit checker. @@ -76,29 +76,22 @@ class GitHubRateLimitChecker { } /** - * Gets the appropriate {@link RateLimitChecker} for a particular target. + * Constructs a new {@link GitHubRateLimitChecker} with a new checker for a particular target. * - * Analogous with {@link GHRateLimit#getRecord(RateLimitTarget)}. + * Only one {@link RateLimitChecker} is allowed per target. * + * @param checker + * the {@link RateLimitChecker} to apply. * @param rateLimitTarget - * the rate limit to check - * @return the {@link RateLimitChecker} for a particular target + * the {@link RateLimitTarget} for this checker. If {@link RateLimitTarget#NONE}, checker will be ignored + * and no change will be made. + * @return a new {@link GitHubRateLimitChecker} */ - @Nonnull - private RateLimitChecker selectChecker(@Nonnull RateLimitTarget rateLimitTarget) { - if (rateLimitTarget == RateLimitTarget.NONE) { - return RateLimitChecker.NONE; - } else if (rateLimitTarget == RateLimitTarget.CORE) { - return core; - } else if (rateLimitTarget == RateLimitTarget.SEARCH) { - return search; - } else if (rateLimitTarget == RateLimitTarget.GRAPHQL) { - return graphql; - } else if (rateLimitTarget == RateLimitTarget.INTEGRATION_MANIFEST) { - return integrationManifest; - } else { - throw new IllegalArgumentException("Unknown rate limit target: " + rateLimitTarget.toString()); - } + GitHubRateLimitChecker with(@Nonnull RateLimitChecker checker, @Nonnull RateLimitTarget rateLimitTarget) { + return new GitHubRateLimitChecker(rateLimitTarget == RateLimitTarget.CORE ? checker : core, + rateLimitTarget == RateLimitTarget.SEARCH ? checker : search, + rateLimitTarget == RateLimitTarget.GRAPHQL ? checker : graphql, + rateLimitTarget == RateLimitTarget.INTEGRATION_MANIFEST ? checker : integrationManifest); } /** @@ -167,21 +160,28 @@ void checkRateLimit(GitHubClient client, @Nonnull RateLimitTarget rateLimitTarge } /** - * Constructs a new {@link GitHubRateLimitChecker} with a new checker for a particular target. + * Gets the appropriate {@link RateLimitChecker} for a particular target. * - * Only one {@link RateLimitChecker} is allowed per target. + * Analogous with {@link GHRateLimit#getRecord(RateLimitTarget)}. * - * @param checker - * the {@link RateLimitChecker} to apply. * @param rateLimitTarget - * the {@link RateLimitTarget} for this checker. If {@link RateLimitTarget#NONE}, checker will be ignored - * and no change will be made. - * @return a new {@link GitHubRateLimitChecker} + * the rate limit to check + * @return the {@link RateLimitChecker} for a particular target */ - GitHubRateLimitChecker with(@Nonnull RateLimitChecker checker, @Nonnull RateLimitTarget rateLimitTarget) { - return new GitHubRateLimitChecker(rateLimitTarget == RateLimitTarget.CORE ? checker : core, - rateLimitTarget == RateLimitTarget.SEARCH ? checker : search, - rateLimitTarget == RateLimitTarget.GRAPHQL ? checker : graphql, - rateLimitTarget == RateLimitTarget.INTEGRATION_MANIFEST ? checker : integrationManifest); + @Nonnull + private RateLimitChecker selectChecker(@Nonnull RateLimitTarget rateLimitTarget) { + if (rateLimitTarget == RateLimitTarget.NONE) { + return RateLimitChecker.NONE; + } else if (rateLimitTarget == RateLimitTarget.CORE) { + return core; + } else if (rateLimitTarget == RateLimitTarget.SEARCH) { + return search; + } else if (rateLimitTarget == RateLimitTarget.GRAPHQL) { + return graphql; + } else if (rateLimitTarget == RateLimitTarget.INTEGRATION_MANIFEST) { + return integrationManifest; + } else { + throw new IllegalArgumentException("Unknown rate limit target: " + rateLimitTarget.toString()); + } } } diff --git a/src/main/java/org/kohsuke/github/GitHubRateLimitHandler.java b/src/main/java/org/kohsuke/github/GitHubRateLimitHandler.java index dd6149b1bd..8cb5911266 100644 --- a/src/main/java/org/kohsuke/github/GitHubRateLimitHandler.java +++ b/src/main/java/org/kohsuke/github/GitHubRateLimitHandler.java @@ -19,40 +19,11 @@ * * @author Kohsuke Kawaguchi * @author Liam Newman - * @see GitHubBuilder#withRateLimitHandler(GitHubRateLimitHandler) + * @see GitHubBuilder#withRateLimitHandler(RateLimitHandler) GitHubBuilder#withRateLimitHandler(RateLimitHandler) * @see GitHubAbuseLimitHandler */ public abstract class GitHubRateLimitHandler extends GitHubConnectorResponseErrorHandler { - /** - * Fail immediately. - */ - public static final GitHubRateLimitHandler FAIL = new GitHubRateLimitHandler() { - @Override - public void onError(GitHubConnectorResponse connectorResponse) throws IOException { - throw new HttpException("API rate limit reached", - connectorResponse.statusCode(), - connectorResponse.header("Status"), - connectorResponse.request().url().toString()) - .withResponseHeaderFields(connectorResponse.allHeaders()); - - } - }; - - /** - * Wait until the API abuse "wait time" is passed. - */ - public static final GitHubRateLimitHandler WAIT = new GitHubRateLimitHandler() { - @Override - public void onError(GitHubConnectorResponse connectorResponse) throws IOException { - try { - Thread.sleep(parseWaitTime(connectorResponse)); - } catch (InterruptedException ex) { - throw (InterruptedIOException) new InterruptedIOException().initCause(ex); - } - } - }; - /** * On a wait, even if the response suggests a very short wait, wait for a minimum duration. */ @@ -64,6 +35,21 @@ public void onError(GitHubConnectorResponse connectorResponse) throws IOExceptio public GitHubRateLimitHandler() { } + /** + * Checks if is error. + * + * @param connectorResponse + * the connector response + * @return true, if is error + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Override + boolean isError(@NotNull GitHubConnectorResponse connectorResponse) throws IOException { + return connectorResponse.statusCode() == HTTP_FORBIDDEN + && "0".equals(connectorResponse.header("X-RateLimit-Remaining")); + } + /** * Called when the library encounters HTTP error indicating that the API rate limit has been exceeded. * @@ -82,19 +68,18 @@ public GitHubRateLimitHandler() { public abstract void onError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException; /** - * Checks if is error. - * - * @param connectorResponse - * the connector response - * @return true, if is error - * @throws IOException - * Signals that an I/O exception has occurred. + * Wait until the API abuse "wait time" is passed. */ - @Override - boolean isError(@NotNull GitHubConnectorResponse connectorResponse) throws IOException { - return connectorResponse.statusCode() == HTTP_FORBIDDEN - && "0".equals(connectorResponse.header("X-RateLimit-Remaining")); - } + public static final GitHubRateLimitHandler WAIT = new GitHubRateLimitHandler() { + @Override + public void onError(GitHubConnectorResponse connectorResponse) throws IOException { + try { + Thread.sleep(parseWaitTime(connectorResponse)); + } catch (InterruptedException ex) { + throw (InterruptedIOException) new InterruptedIOException().initCause(ex); + } + } + }; /* * Exposed for testability. Given an http response, find the rate limit reset header field and parse it. If no @@ -118,4 +103,19 @@ long parseWaitTime(GitHubConnectorResponse connectorResponse) { return Math.max(MINIMUM_RATE_LIMIT_RETRY_MILLIS, (Long.parseLong(v) - now.toInstant().getEpochSecond()) * 1000); } + /** + * Fail immediately. + */ + public static final GitHubRateLimitHandler FAIL = new GitHubRateLimitHandler() { + @Override + public void onError(GitHubConnectorResponse connectorResponse) throws IOException { + throw new HttpException("API rate limit reached", + connectorResponse.statusCode(), + connectorResponse.header("Status"), + connectorResponse.request().url().toString()) + .withResponseHeaderFields(connectorResponse.allHeaders()); + + } + }; + } diff --git a/src/main/java/org/kohsuke/github/GitHubRequest.java b/src/main/java/org/kohsuke/github/GitHubRequest.java index 20cf1462a4..2bb4a459a8 100644 --- a/src/main/java/org/kohsuke/github/GitHubRequest.java +++ b/src/main/java/org/kohsuke/github/GitHubRequest.java @@ -38,29 +38,278 @@ */ public class GitHubRequest implements GitHubConnectorRequest { + private static final Comparator nullableCaseInsensitiveComparator = Comparator + .nullsFirst(String.CASE_INSENSITIVE_ORDER); + + private static final List METHODS_WITHOUT_BODY = asList("GET", "DELETE"); + private final List args; + private final Map> headers; + private final Map injectedMappingValues; + private final String apiUrl; + private final String urlPath; + private final String method; + private final RateLimitTarget rateLimitTarget; + private final byte[] body; + private final boolean forceBody; + + private final URL url; + + @SuppressFBWarnings(value = { "CT_CONSTRUCTOR_THROW" }, justification = "Basic argument validation") + private GitHubRequest(@Nonnull List args, + @Nonnull Map> headers, + @Nonnull Map injectedMappingValues, + @Nonnull String apiUrl, + @Nonnull String urlPath, + @Nonnull String method, + @Nonnull RateLimitTarget rateLimitTarget, + @CheckForNull byte[] body, + boolean forceBody) { + this.args = Collections.unmodifiableList(new ArrayList<>(args)); + TreeMap> caseInsensitiveMap = new TreeMap<>(nullableCaseInsensitiveComparator); + for (Map.Entry> entry : headers.entrySet()) { + caseInsensitiveMap.put(entry.getKey(), Collections.unmodifiableList(new ArrayList<>(entry.getValue()))); + } + this.headers = Collections.unmodifiableMap(caseInsensitiveMap); + this.injectedMappingValues = Collections.unmodifiableMap(new LinkedHashMap<>(injectedMappingValues)); + this.apiUrl = apiUrl; + this.urlPath = urlPath; + this.method = method; + this.rateLimitTarget = rateLimitTarget; + this.body = body; + this.forceBody = forceBody; + String tailApiUrl = buildTailApiUrl(); + url = getApiURL(apiUrl, tailApiUrl); + } + /** - * The Class Entry. + * Create a new {@link Builder}. + * + * @return a new {@link Builder}. */ - protected static class Entry { + static Builder newBuilder() { + return new Builder<>(); + } - /** The key. */ - final String key; + /** + * Gets the final GitHub API URL. + * + * @param apiUrl + * the api url + * @param tailApiUrl + * the tail api url + * @return the api URL + * @throws GHException + * wrapping a {@link MalformedURLException} if the GitHub API URL cannot be constructed + */ + @Nonnull + static URL getApiURL(String apiUrl, String tailApiUrl) { + try { + if (!tailApiUrl.startsWith("/")) { + apiUrl = ""; + } else if ("github.com".equals(apiUrl)) { + // backward compatibility + apiUrl = GitHubClient.GITHUB_URL; + } + return new URI(apiUrl + tailApiUrl).toURL(); + } catch (Exception e) { + // The data going into constructing this URL should be controlled by the GitHub API framework, + // so a malformed URL here is a framework runtime error. + // All callers of this method ended up wrapping and throwing GHException, + // indicating the functionality should be moved to the common code path. + throw new GHException("Unable to build GitHub API URL", e); + } + } - /** The value. */ - final Object value; + /** + * Transform Java Enum into Github constants given its conventions. + * + * @param en + * Enum to be transformed + * @return a String containing the value of a Github constant + */ + static String transformEnum(Enum en) { + // by convention Java constant names are upper cases, but github uses + // lower-case constants. GitHub also uses '-', which in Java we always + // replace with '_' + return en.toString().toLowerCase(Locale.ENGLISH).replace('_', '-'); + } - /** - * Instantiates a new entry. - * - * @param key - * the key - * @param value - * the value - */ - protected Entry(String key, Object value) { - this.key = key; - this.value = value; + /** + * The method for this request, such as "GET", "PATCH", or "DELETE". + * + * @return the request method. + */ + @Override + @Nonnull + public String method() { + return method; + } + + /** + * The rate limit target for this request. + * + * @return the rate limit to use for this request. + */ + @Nonnull + public RateLimitTarget rateLimitTarget() { + return rateLimitTarget; + } + + /** + * The arguments for this request. Depending on the {@link #method()} and {@code #inBody()} these maybe added to the + * url or to the request body. + * + * @return the list of arguments + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Already unmodifiable") + @Nonnull + public List args() { + return args; + } + + /** + * The headers for this request. + * + * @return the {@link Map} of headers + */ + @Override + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable Map of unmodifiable lists") + @Nonnull + public Map> allHeaders() { + return headers; + } + + /** + * Gets the first value of a header field for this request. + * + * @param name + * the name of the header field. + * @return the value of the header field, or {@code null} if the header isn't set. + */ + @CheckForNull + public String header(String name) { + List values = headers.get(name); + if (values != null) { + return values.get(0); + } + return null; + } + + /** + * The headers for this request. + * + * @return the {@link Map} of headers + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Already unmodifiable") + @Nonnull + public Map injectedMappingValues() { + return injectedMappingValues; + } + + /** + * The base GitHub API URL for this request represented as a {@link String}. + * + * @return the url string + */ + @Nonnull + public String apiUrl() { + return apiUrl; + } + + /** + * The url path to be added to the {@link #apiUrl()} for this request. If this does not start with a "/", it instead + * represents the full url string for this request. + * + * @return a url path or full url string + */ + @Nonnull + public String urlPath() { + return urlPath; + } + + /** + * The content type to be sent by this request. + * + * @return the content type. + */ + @Override + public String contentType() { + return header("Content-type"); + } + + /** + * The {@link InputStream} to be sent as the body of this request. + * + * @return the {@link InputStream}. + */ + @Override + @CheckForNull + public InputStream body() { + return body != null ? new ByteArrayInputStream(body) : null; + } + + /** + * The {@link URL} for this request. This is the actual URL the {@link GitHubClient} will send this request to. + * + * @return the request {@link URL} + */ + @Override + @Nonnull + public URL url() { + return url; + } + + /** + * Whether arguments for this request should be included in the URL or in the body of the request. + * + * @return true if the arguments should be sent in the body of the request. + */ + @Override + public boolean hasBody() { + return forceBody || !METHODS_WITHOUT_BODY.contains(method); + } + + /** + * Create a {@link Builder} from this request. Initial values of the builder will be the same as this + * {@link GitHubRequest}. + * + * @return a {@link Builder} based on this request. + */ + Builder toBuilder() { + return new Builder<>(args, + headers, + injectedMappingValues, + apiUrl, + urlPath, + method, + rateLimitTarget, + body, + forceBody); + } + + private String buildTailApiUrl() { + String tailApiUrl = urlPath; + if (!hasBody() && !args.isEmpty() && tailApiUrl.startsWith("/")) { + try { + StringBuilder argString = new StringBuilder(); + boolean questionMarkFound = tailApiUrl.indexOf('?') != -1; + argString.append(questionMarkFound ? '&' : '?'); + + for (Iterator it = args.listIterator(); it.hasNext();) { + Entry arg = it.next(); + argString.append(URLEncoder.encode(arg.key, StandardCharsets.UTF_8.name())); + argString.append('='); + argString.append(URLEncoder.encode(arg.value.toString(), StandardCharsets.UTF_8.name())); + if (it.hasNext()) { + argString.append('&'); + } + } + tailApiUrl += argString; + } catch (UnsupportedEncodingException e) { + throw new GHException("UTF-8 encoding required", e); + } } + return tailApiUrl; } /** @@ -71,30 +320,29 @@ protected Entry(String key, Object value) { */ static class Builder> { - /** - * The base GitHub API for this request. - */ - @Nonnull - private String apiUrl; - @Nonnull private final List args; - private byte[] body; - - private boolean forceBody; - /** * The header values for this request. */ @Nonnull private final Map> headers; + /** * Injected local data map */ @Nonnull private final Map injectedMappingValues; + /** + * The base GitHub API for this request. + */ + @Nonnull + private String apiUrl; + + @Nonnull + private String urlPath; /** * Request method. */ @@ -103,8 +351,24 @@ static class Builder> { @Nonnull private RateLimitTarget rateLimitTarget; - @Nonnull - private String urlPath; + + private byte[] body; + private boolean forceBody; + + /** + * Create a new {@link GitHubRequest.Builder} + */ + protected Builder() { + this(new ArrayList<>(), + new TreeMap<>(nullableCaseInsensitiveComparator), + new LinkedHashMap<>(), + GitHubClient.GITHUB_URL, + "/", + "GET", + RateLimitTarget.CORE, + null, + false); + } private Builder(@Nonnull List args, @Nonnull Map> headers, @@ -130,21 +394,6 @@ private Builder(@Nonnull List args, this.forceBody = forceBody; } - /** - * Create a new {@link GitHubRequest.Builder} - */ - protected Builder() { - this(new ArrayList<>(), - new TreeMap<>(nullableCaseInsensitiveComparator), - new LinkedHashMap<>(), - GitHubClient.GITHUB_URL, - "/", - "GET", - RateLimitTarget.CORE, - null, - false); - } - /** * Builds a {@link GitHubRequest} from this builder. * @@ -165,42 +414,33 @@ public GitHubRequest build() { } /** - * Content type requester. + * With header requester. * - * @param contentType - * the content type + * @param url + * the url * @return the request builder */ - public B contentType(String contentType) { - this.setHeader("Content-type", contentType); + public B withApiUrl(String url) { + this.apiUrl = url; return (B) this; } /** - * Small number of GitHub APIs use HTTP methods somewhat inconsistently, and use a body where it's not expected. - * Normally whether parameters go as query parameters or a body depends on the HTTP verb in use, but this method - * forces the parameters to be sent as a body. + * Removes the named request HTTP header. * + * @param name + * the name * @return the request builder */ - public B inBody() { - forceBody = true; + public B removeHeader(String name) { + headers.remove(name); return (B) this; } /** - * Object to inject into binding. - * - * @param value - * the value - * @return the request builder - */ - public B injectMappingValue(@NonNull Object value) { - return injectMappingValue(value.getClass().getName(), value); - } - - /** - * Object to inject into binding. + * Sets the request HTTP header. + *

+ * If a header of the same name is already set, this method overrides it. * * @param name * the name @@ -208,84 +448,45 @@ public B injectMappingValue(@NonNull Object value) { * the value * @return the request builder */ - public B injectMappingValue(@NonNull String name, Object value) { - this.injectedMappingValues.put(name, value); - return (B) this; - } - - /** - * Method requester. - * - * @param method - * the method - * @return the request builder - */ - public B method(@Nonnull String method) { - this.method = method; - return (B) this; - } - - /** - * Method requester. - * - * @param rateLimitTarget - * the rate limit target for this request. Default is {@link RateLimitTarget#CORE}. - * @return the request builder - */ - public B rateLimit(@Nonnull RateLimitTarget rateLimitTarget) { - this.rateLimitTarget = rateLimitTarget; - return (B) this; - } - - /** - * Removes all arg entries for a specific key. - * - * @param key - * the key - * @return the request builder - */ - public B remove(String key) { - for (int index = 0; index < args.size();) { - if (args.get(index).key.equals(key)) { - args.remove(index); - } else { - index++; - } - } + public B setHeader(String name, String value) { + List field = new ArrayList<>(); + field.add(value); + headers.put(name, field); return (B) this; } /** - * Removes the named request HTTP header. + * With header requester. * * @param name * the name + * @param value + * the value * @return the request builder */ - public B removeHeader(String name) { - headers.remove(name); + public B withHeader(String name, String value) { + List field = headers.get(name); + if (field == null) { + setHeader(name, value); + } else { + field.add(value); + } return (B) this; } /** - * Unlike {@link #with(String, String)}, overrides the existing value. + * Object to inject into binding. * - * @param key - * the key * @param value * the value * @return the request builder */ - public B set(String key, Object value) { - remove(key); - return with(key, value); - + public B injectMappingValue(@NonNull Object value) { + return injectMappingValue(value.getClass().getName(), value); } /** - * Sets the request HTTP header. - *

- * If a header of the same name is already set, this method overrides it. + * Object to inject into binding. * * @param name * the name @@ -293,26 +494,20 @@ public B set(String key, Object value) { * the value * @return the request builder */ - public B setHeader(String name, String value) { - List field = new ArrayList<>(); - field.add(value); - headers.put(name, field); + public B injectMappingValue(@NonNull String name, Object value) { + this.injectedMappingValues.put(name, value); return (B) this; } /** - * With requester. + * With preview. * - * @param body - * the body - * @return the request builder - * @throws IOException - * Signals that an I/O exception has occurred. + * @param name + * the name + * @return the b */ - public B with(@WillClose InputStream body) throws IOException { - this.body = IOUtils.toByteArray(body); - IOUtils.closeQuietly(body); - return (B) this; + public B withAccept(String name) { + return withHeader("Accept", name); } /** @@ -339,25 +534,10 @@ public B with(Map map) { * the value * @return the request builder */ - public B with(String key, Collection value) { + public B with(String key, int value) { return with(key, (Object) value); } - /** - * With requester. - * - * @param key - * the key - * @param e - * the e - * @return the request builder - */ - public B with(String key, Enum e) { - if (e == null) - return with(key, (Object) null); - return with(key, transformEnum(e)); - } - /** * With requester. * @@ -367,7 +547,7 @@ public B with(String key, Enum e) { * the value * @return the request builder */ - public B with(String key, Map value) { + public B with(String key, long value) { return with(key, (Object) value); } @@ -377,14 +557,11 @@ public B with(String key, Map value) { * @param key * the key * @param value - * the value - * @return the request builder - */ - public B with(String key, Object value) { - if (value != null) { - args.add(new Entry(key, value)); - } - return (B) this; + * the value + * @return the request builder + */ + public B with(String key, boolean value) { + return with(key, (Object) value); } /** @@ -392,12 +569,14 @@ public B with(String key, Object value) { * * @param key * the key - * @param value - * the value + * @param e + * the e * @return the request builder */ - public B with(String key, String value) { - return with(key, (Object) value); + public B with(String key, Enum e) { + if (e == null) + return with(key, (Object) null); + return with(key, transformEnum(e)); } /** @@ -409,7 +588,7 @@ public B with(String key, String value) { * the value * @return the request builder */ - public B with(String key, boolean value) { + public B with(String key, String value) { return with(key, (Object) value); } @@ -422,7 +601,7 @@ public B with(String key, boolean value) { * the value * @return the request builder */ - public B with(String key, int value) { + public B with(String key, Collection value) { return with(key, (Object) value); } @@ -435,54 +614,57 @@ public B with(String key, int value) { * the value * @return the request builder */ - public B with(String key, long value) { + public B with(String key, Map value) { return with(key, (Object) value); } /** - * With preview. + * With requester. * - * @param name - * the name - * @return the b + * @param body + * the body + * @return the request builder + * @throws IOException + * Signals that an I/O exception has occurred. */ - public B withAccept(String name) { - return withHeader("Accept", name); + public B with(@WillClose InputStream body) throws IOException { + this.body = IOUtils.toByteArray(body); + IOUtils.closeQuietly(body); + return (B) this; } /** - * With header requester. + * With nullable requester. * - * @param url - * the url + * @param key + * the key + * @param value + * the value * @return the request builder */ - public B withApiUrl(String url) { - this.apiUrl = url; + public B withNullable(String key, Object value) { + args.add(new Entry(key, value)); return (B) this; } /** - * With header requester. + * With requester. * - * @param name - * the name + * @param key + * the key * @param value * the value * @return the request builder */ - public B withHeader(String name, String value) { - List field = headers.get(name); - if (field == null) { - setHeader(name, value); - } else { - field.add(value); + public B with(String key, Object value) { + if (value != null) { + args.add(new Entry(key, value)); } return (B) this; } /** - * With nullable requester. + * Unlike {@link #with(String, String)}, overrides the existing value. * * @param key * the key @@ -490,356 +672,174 @@ public B withHeader(String name, String value) { * the value * @return the request builder */ - public B withNullable(String key, Object value) { - args.add(new Entry(key, value)); - return (B) this; + public B set(String key, Object value) { + remove(key); + return with(key, value); + } /** - * Path component of api URL. Appended to api url. - *

- * If urlPath starts with a slash, it will be URI encoded as a path. If it starts with anything else, it will be - * used as is. + * Removes all arg entries for a specific key. * - * @param urlPath - * the url path - * @param urlPathItems - * the content type + * @param key + * the key * @return the request builder */ - public B withUrlPath(@Nonnull String urlPath, @Nonnull String... urlPathItems) { - // full url may be set and reset as needed - if (urlPathItems.length == 0 && !urlPath.startsWith("/")) { - return setRawUrlPath(urlPath); - } - - // Once full url is set, do not allow path setting - if (!this.urlPath.startsWith("/")) { - throw new GHException("Cannot append to url path after setting a full url"); - } - - String tailUrlPath = urlPath; - if (urlPathItems.length != 0) { - tailUrlPath += "/" + String.join("/", urlPathItems); + public B remove(String key) { + for (int index = 0; index < args.size();) { + if (args.get(index).key.equals(key)) { + args.remove(index); + } else { + index++; + } } - - tailUrlPath = StringUtils.prependIfMissing(tailUrlPath, "/"); - - this.urlPath = urlPathEncode(tailUrlPath); return (B) this; } /** - * NOT FOR PUBLIC USE. Do not make this method public. - *

- * Sets the path component of api URL without URI encoding. - *

- * Should only be used when passing a literal URL field from a GHObject, such as {@link GHContent#refresh()} or - * when needing to set query parameters on requests methods that don't usually have them, such as - * {@link GHRelease#uploadAsset(String, InputStream, String)}. + * Method requester. * - * @param rawUrlPath - * the content type + * @param method + * the method * @return the request builder */ - B setRawUrlPath(@Nonnull String rawUrlPath) { - Objects.requireNonNull(rawUrlPath); - // This method should only work for full urls, which must start with "http" - if (!rawUrlPath.startsWith("http")) { - throw new GHException("Raw URL must start with 'http'"); - } - this.urlPath = rawUrlPath; - return (B) this; - } - } - private static final List METHODS_WITHOUT_BODY = asList("GET", "DELETE"); - private static final Comparator nullableCaseInsensitiveComparator = Comparator - .nullsFirst(String.CASE_INSENSITIVE_ORDER); - /** - * Encode the path to url safe string. - * - * @param value - * string to be path encoded. - * @return The encoded string. - */ - private static String urlPathEncode(String value) { - try { - return new URI(null, null, value, null, null).toASCIIString(); - } catch (URISyntaxException ex) { - throw new AssertionError(ex); - } - } - /** - * Gets the final GitHub API URL. - * - * @param apiUrl - * the api url - * @param tailApiUrl - * the tail api url - * @return the api URL - * @throws GHException - * wrapping a {@link MalformedURLException} if the GitHub API URL cannot be constructed - */ - @Nonnull - static URL getApiURL(String apiUrl, String tailApiUrl) { - try { - if (!tailApiUrl.startsWith("/")) { - apiUrl = ""; - } else if ("github.com".equals(apiUrl)) { - // backward compatibility - apiUrl = GitHubClient.GITHUB_URL; - } - return new URI(apiUrl + tailApiUrl).toURL(); - } catch (Exception e) { - // The data going into constructing this URL should be controlled by the GitHub API framework, - // so a malformed URL here is a framework runtime error. - // All callers of this method ended up wrapping and throwing GHException, - // indicating the functionality should be moved to the common code path. - throw new GHException("Unable to build GitHub API URL", e); - } - } - /** - * Create a new {@link Builder}. - * - * @return a new {@link Builder}. - */ - static Builder newBuilder() { - return new Builder<>(); - } - /** - * Transform Java Enum into Github constants given its conventions. - * - * @param en - * Enum to be transformed - * @return a String containing the value of a Github constant - */ - static String transformEnum(Enum en) { - // by convention Java constant names are upper cases, but github uses - // lower-case constants. GitHub also uses '-', which in Java we always - // replace with '_' - return en.toString().toLowerCase(Locale.ENGLISH).replace('_', '-'); - } - private final String apiUrl; - private final List args; - private final byte[] body; - - private final boolean forceBody; - - private final Map> headers; - - private final Map injectedMappingValues; - - private final String method; - - private final RateLimitTarget rateLimitTarget; - - private final URL url; - - private final String urlPath; - - @SuppressFBWarnings(value = { "CT_CONSTRUCTOR_THROW" }, justification = "Basic argument validation") - private GitHubRequest(@Nonnull List args, - @Nonnull Map> headers, - @Nonnull Map injectedMappingValues, - @Nonnull String apiUrl, - @Nonnull String urlPath, - @Nonnull String method, - @Nonnull RateLimitTarget rateLimitTarget, - @CheckForNull byte[] body, - boolean forceBody) { - this.args = Collections.unmodifiableList(new ArrayList<>(args)); - TreeMap> caseInsensitiveMap = new TreeMap<>(nullableCaseInsensitiveComparator); - for (Map.Entry> entry : headers.entrySet()) { - caseInsensitiveMap.put(entry.getKey(), Collections.unmodifiableList(new ArrayList<>(entry.getValue()))); - } - this.headers = Collections.unmodifiableMap(caseInsensitiveMap); - this.injectedMappingValues = Collections.unmodifiableMap(new LinkedHashMap<>(injectedMappingValues)); - this.apiUrl = apiUrl; - this.urlPath = urlPath; - this.method = method; - this.rateLimitTarget = rateLimitTarget; - this.body = body; - this.forceBody = forceBody; - String tailApiUrl = buildTailApiUrl(); - url = getApiURL(apiUrl, tailApiUrl); - } - - /** - * The headers for this request. - * - * @return the {@link Map} of headers - */ - @Override - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable Map of unmodifiable lists") - @Nonnull - public Map> allHeaders() { - return headers; - } + public B method(@Nonnull String method) { + this.method = method; + return (B) this; + } - /** - * The base GitHub API URL for this request represented as a {@link String}. - * - * @return the url string - */ - @Nonnull - public String apiUrl() { - return apiUrl; - } + /** + * Method requester. + * + * @param rateLimitTarget + * the rate limit target for this request. Default is {@link RateLimitTarget#CORE}. + * @return the request builder + */ + public B rateLimit(@Nonnull RateLimitTarget rateLimitTarget) { + this.rateLimitTarget = rateLimitTarget; + return (B) this; + } - /** - * The arguments for this request. Depending on the {@link #method()} and {@code #inBody()} these maybe added to the - * url or to the request body. - * - * @return the list of arguments - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Already unmodifiable") - @Nonnull - public List args() { - return args; - } + /** + * Content type requester. + * + * @param contentType + * the content type + * @return the request builder + */ + public B contentType(String contentType) { + this.setHeader("Content-type", contentType); + return (B) this; + } - /** - * The {@link InputStream} to be sent as the body of this request. - * - * @return the {@link InputStream}. - */ - @Override - @CheckForNull - public InputStream body() { - return body != null ? new ByteArrayInputStream(body) : null; - } + /** + * NOT FOR PUBLIC USE. Do not make this method public. + *

+ * Sets the path component of api URL without URI encoding. + *

+ * Should only be used when passing a literal URL field from a GHObject, such as {@link GHContent#refresh()} or + * when needing to set query parameters on requests methods that don't usually have them, such as + * {@link GHRelease#uploadAsset(String, InputStream, String)}. + * + * @param rawUrlPath + * the content type + * @return the request builder + */ + B setRawUrlPath(@Nonnull String rawUrlPath) { + Objects.requireNonNull(rawUrlPath); + // This method should only work for full urls, which must start with "http" + if (!rawUrlPath.startsWith("http")) { + throw new GHException("Raw URL must start with 'http'"); + } + this.urlPath = rawUrlPath; + return (B) this; + } - /** - * The content type to be sent by this request. - * - * @return the content type. - */ - @Override - public String contentType() { - return header("Content-type"); - } + /** + * Path component of api URL. Appended to api url. + *

+ * If urlPath starts with a slash, it will be URI encoded as a path. If it starts with anything else, it will be + * used as is. + * + * @param urlPath + * the url path + * @param urlPathItems + * the content type + * @return the request builder + */ + public B withUrlPath(@Nonnull String urlPath, @Nonnull String... urlPathItems) { + // full url may be set and reset as needed + if (urlPathItems.length == 0 && !urlPath.startsWith("/")) { + return setRawUrlPath(urlPath); + } - /** - * Whether arguments for this request should be included in the URL or in the body of the request. - * - * @return true if the arguments should be sent in the body of the request. - */ - @Override - public boolean hasBody() { - return forceBody || !METHODS_WITHOUT_BODY.contains(method); - } + // Once full url is set, do not allow path setting + if (!this.urlPath.startsWith("/")) { + throw new GHException("Cannot append to url path after setting a full url"); + } - /** - * Gets the first value of a header field for this request. - * - * @param name - * the name of the header field. - * @return the value of the header field, or {@code null} if the header isn't set. - */ - @CheckForNull - public String header(String name) { - List values = headers.get(name); - if (values != null) { - return values.get(0); - } - return null; - } + String tailUrlPath = urlPath; + if (urlPathItems.length != 0) { + tailUrlPath += "/" + String.join("/", urlPathItems); + } - /** - * The headers for this request. - * - * @return the {@link Map} of headers - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Already unmodifiable") - @Nonnull - public Map injectedMappingValues() { - return injectedMappingValues; - } + tailUrlPath = StringUtils.prependIfMissing(tailUrlPath, "/"); - /** - * The method for this request, such as "GET", "PATCH", or "DELETE". - * - * @return the request method. - */ - @Override - @Nonnull - public String method() { - return method; - } + this.urlPath = urlPathEncode(tailUrlPath); + return (B) this; + } - /** - * The rate limit target for this request. - * - * @return the rate limit to use for this request. - */ - @Nonnull - public RateLimitTarget rateLimitTarget() { - return rateLimitTarget; + /** + * Small number of GitHub APIs use HTTP methods somewhat inconsistently, and use a body where it's not expected. + * Normally whether parameters go as query parameters or a body depends on the HTTP verb in use, but this method + * forces the parameters to be sent as a body. + * + * @return the request builder + */ + public B inBody() { + forceBody = true; + return (B) this; + } } /** - * The {@link URL} for this request. This is the actual URL the {@link GitHubClient} will send this request to. - * - * @return the request {@link URL} + * The Class Entry. */ - @Override - @Nonnull - public URL url() { - return url; - } + protected static class Entry { - /** - * The url path to be added to the {@link #apiUrl()} for this request. If this does not start with a "/", it instead - * represents the full url string for this request. - * - * @return a url path or full url string - */ - @Nonnull - public String urlPath() { - return urlPath; - } + /** The key. */ + final String key; - private String buildTailApiUrl() { - String tailApiUrl = urlPath; - if (!hasBody() && !args.isEmpty() && tailApiUrl.startsWith("/")) { - try { - StringBuilder argString = new StringBuilder(); - boolean questionMarkFound = tailApiUrl.indexOf('?') != -1; - argString.append(questionMarkFound ? '&' : '?'); + /** The value. */ + final Object value; - for (Iterator it = args.listIterator(); it.hasNext();) { - Entry arg = it.next(); - argString.append(URLEncoder.encode(arg.key, StandardCharsets.UTF_8.name())); - argString.append('='); - argString.append(URLEncoder.encode(arg.value.toString(), StandardCharsets.UTF_8.name())); - if (it.hasNext()) { - argString.append('&'); - } - } - tailApiUrl += argString; - } catch (UnsupportedEncodingException e) { - throw new GHException("UTF-8 encoding required", e); - } + /** + * Instantiates a new entry. + * + * @param key + * the key + * @param value + * the value + */ + protected Entry(String key, Object value) { + this.key = key; + this.value = value; } - return tailApiUrl; } /** - * Create a {@link Builder} from this request. Initial values of the builder will be the same as this - * {@link GitHubRequest}. + * Encode the path to url safe string. * - * @return a {@link Builder} based on this request. + * @param value + * string to be path encoded. + * @return The encoded string. */ - Builder toBuilder() { - return new Builder<>(args, - headers, - injectedMappingValues, - apiUrl, - urlPath, - method, - rateLimitTarget, - body, - forceBody); + private static String urlPathEncode(String value) { + try { + return new URI(null, null, value, null, null).toASCIIString(); + } catch (URISyntaxException ex) { + throw new AssertionError(ex); + } } } diff --git a/src/main/java/org/kohsuke/github/GitHubResponse.java b/src/main/java/org/kohsuke/github/GitHubResponse.java index 8ac65391f7..fc8cb02f28 100644 --- a/src/main/java/org/kohsuke/github/GitHubResponse.java +++ b/src/main/java/org/kohsuke/github/GitHubResponse.java @@ -35,40 +35,44 @@ class GitHubResponse { private static final Logger LOGGER = Logger.getLogger(GitHubResponse.class.getName()); + private final int statusCode; + + @Nonnull + private final Map> headers; + + @CheckForNull + private final T body; + /** - * Gets the body of the response as a {@link String}. + * Instantiates a new git hub response. * - * @param connectorResponse - * the response to read - * @return the body of the response as a {@link String}. - * @throws IOException - * if an I/O Exception occurs. + * @param response + * the response + * @param body + * the body */ - @Nonnull - static String getBodyAsString(GitHubConnectorResponse connectorResponse) throws IOException { - InputStream inputStream = connectorResponse.bodyStream(); - try (InputStreamReader r = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { - return IOUtils.toString(r); - } + GitHubResponse(GitHubResponse response, @CheckForNull T body) { + this.statusCode = response.statusCode(); + this.headers = response.headers; + this.body = body; } /** - * Gets the body of the response as a {@link String}. + * Instantiates a new git hub response. * * @param connectorResponse - * the response to read - * @return the body of the response as a {@link String}. + * the connector response + * @param body + * the body */ - static String getBodyAsStringOrNull(GitHubConnectorResponse connectorResponse) { - try { - return getBodyAsString(connectorResponse); - } catch (IOException e) { - } - return null; + GitHubResponse(GitHubConnectorResponse connectorResponse, @CheckForNull T body) { + this.statusCode = connectorResponse.statusCode(); + this.headers = connectorResponse.allHeaders(); + this.body = body; } /** - * Parses a {@link GitHubConnectorResponse} body into a new instance of {@code T}. + * Parses a {@link GitHubConnectorResponse} body into a new instance of {@link T}. * * @param * the type @@ -76,7 +80,7 @@ static String getBodyAsStringOrNull(GitHubConnectorResponse connectorResponse) { * response info to parse. * @param type * the type to be constructed. - * @return a new instance of {@code T}. + * @return a new instance of {@link T}. * @throws IOException * if there is an I/O Exception. */ @@ -107,7 +111,7 @@ static T parseBody(GitHubConnectorResponse connectorResponse, Class type) } /** - * Parses a {@link GitHubConnectorResponse} body into a new instance of {@code T}. + * Parses a {@link GitHubConnectorResponse} body into a new instance of {@link T}. * * @param * the type @@ -115,7 +119,7 @@ static T parseBody(GitHubConnectorResponse connectorResponse, Class type) * response info to parse. * @param instance * the object to fill with data parsed from body - * @return a new instance of {@code T}. + * @return a new instance of {@link T}. * @throws IOException * if there is an I/O Exception. */ @@ -132,49 +136,57 @@ static T parseBody(GitHubConnectorResponse connectorResponse, T instance) th } } - @CheckForNull - private final T body; - + /** + * Gets the body of the response as a {@link String}. + * + * @param connectorResponse + * the response to read + * @return the body of the response as a {@link String}. + * @throws IOException + * if an I/O Exception occurs. + */ @Nonnull - private final Map> headers; - - private final int statusCode; + static String getBodyAsString(GitHubConnectorResponse connectorResponse) throws IOException { + InputStream inputStream = connectorResponse.bodyStream(); + try (InputStreamReader r = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + return IOUtils.toString(r); + } + } /** - * Instantiates a new git hub response. + * Gets the body of the response as a {@link String}. * * @param connectorResponse - * the connector response - * @param body - * the body + * the response to read + * @return the body of the response as a {@link String}. */ - GitHubResponse(GitHubConnectorResponse connectorResponse, @CheckForNull T body) { - this.statusCode = connectorResponse.statusCode(); - this.headers = connectorResponse.allHeaders(); - this.body = body; + static String getBodyAsStringOrNull(GitHubConnectorResponse connectorResponse) { + try { + return getBodyAsString(connectorResponse); + } catch (IOException e) { + } + return null; } /** - * Instantiates a new git hub response. + * The status code for this response. * - * @param response - * the response - * @param body - * the body + * @return the status code for this response. */ - GitHubResponse(GitHubResponse response, @CheckForNull T body) { - this.statusCode = response.statusCode(); - this.headers = response.headers; - this.body = body; + public int statusCode() { + return statusCode; } /** - * The body of the response parsed as a {@code T}. + * The headers for this response. * - * @return body of the response + * @param field + * the field + * @return the headers for this response. */ - public T body() { - return body; + @Nonnull + public List headers(String field) { + return headers.get(field); } /** @@ -195,24 +207,12 @@ public String header(String name) { } /** - * The headers for this response. + * The body of the response parsed as a {@link T}. * - * @param field - * the field - * @return the headers for this response. - */ - @Nonnull - public List headers(String field) { - return headers.get(field); - } - - /** - * The status code for this response. - * - * @return the status code for this response. + * @return body of the response */ - public int statusCode() { - return statusCode; + public T body() { + return body; } } diff --git a/src/main/java/org/kohsuke/github/GitHubSanityCachedValue.java b/src/main/java/org/kohsuke/github/GitHubSanityCachedValue.java index b82ae79e6c..8b5de1874b 100644 --- a/src/main/java/org/kohsuke/github/GitHubSanityCachedValue.java +++ b/src/main/java/org/kohsuke/github/GitHubSanityCachedValue.java @@ -10,41 +10,41 @@ */ class GitHubSanityCachedValue { + private final Object lock = new Object(); private long lastQueriedAtEpochSeconds = 0; private T lastResult = null; - private final Object lock = new Object(); /** * Gets the value from the cache or calls the supplier if the cache is empty or out of date. * - * @param isExpired - * a supplier that returns true if the cached value is no longer valid. * @param query * a supplier the returns an updated value. Only called if the cache is empty or out of date. * @return the value from the cache or the value returned from the supplier. * @throws E * the exception thrown by the supplier if it fails. */ - T get(Function isExpired, SupplierThrows query) throws E { - synchronized (lock) { - if (Instant.now().getEpochSecond() > lastQueriedAtEpochSeconds || isExpired.apply(lastResult)) { - lastResult = query.get(); - lastQueriedAtEpochSeconds = Instant.now().getEpochSecond(); - } - } - return lastResult; + T get(SupplierThrows query) throws E { + return get((value) -> Boolean.FALSE, query); } /** * Gets the value from the cache or calls the supplier if the cache is empty or out of date. * + * @param isExpired + * a supplier that returns true if the cached value is no longer valid. * @param query * a supplier the returns an updated value. Only called if the cache is empty or out of date. * @return the value from the cache or the value returned from the supplier. * @throws E * the exception thrown by the supplier if it fails. */ - T get(SupplierThrows query) throws E { - return get((value) -> Boolean.FALSE, query); + T get(Function isExpired, SupplierThrows query) throws E { + synchronized (lock) { + if (Instant.now().getEpochSecond() > lastQueriedAtEpochSeconds || isExpired.apply(lastResult)) { + lastResult = query.get(); + lastQueriedAtEpochSeconds = Instant.now().getEpochSecond(); + } + } + return lastResult; } } diff --git a/src/main/java/org/kohsuke/github/GitUser.java b/src/main/java/org/kohsuke/github/GitUser.java index 65308ec7a9..d906bc519a 100644 --- a/src/main/java/org/kohsuke/github/GitUser.java +++ b/src/main/java/org/kohsuke/github/GitUser.java @@ -1,9 +1,7 @@ package org.kohsuke.github; -import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.time.Instant; import java.util.Date; import javax.annotation.CheckForNull; @@ -19,24 +17,16 @@ */ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD" }, justification = "JSON API") -public class GitUser extends GitHubBridgeAdapterObject { +public class GitUser { private String name, email, date, username; /** - * Instantiates a new git user. - */ - public GitUser() { - // Empty constructor for Jackson binding - } - - /** - * Gets date. + * Gets the git user name for an author or committer on a git commit. * - * @return Commit Date. + * @return Human readable name of the user, such as "Kohsuke Kawaguchi" */ - @WithBridgeMethods(value = Date.class, adapterMethod = "instantToDate") - public Instant getDate() { - return GitHubClient.parseInstant(date); + public String getName() { + return name; } /** @@ -48,15 +38,6 @@ public String getEmail() { return email; } - /** - * Gets the git user name for an author or committer on a git commit. - * - * @return Human readable name of the user, such as "Kohsuke Kawaguchi" - */ - public String getName() { - return name; - } - /** * Gets username. Note: it presents only in events. * @@ -66,4 +47,20 @@ public String getName() { public String getUsername() { return username; } + + /** + * Gets date. + * + * @return Commit Date. + */ + public Date getDate() { + return GitHubClient.parseDate(date); + } + + /** + * Instantiates a new git user. + */ + public GitUser() { + // Empty constructor for Jackson binding + } } diff --git a/src/main/java/org/kohsuke/github/HttpException.java b/src/main/java/org/kohsuke/github/HttpException.java index c321683f5b..3ced606965 100644 --- a/src/main/java/org/kohsuke/github/HttpException.java +++ b/src/main/java/org/kohsuke/github/HttpException.java @@ -27,20 +27,6 @@ public class HttpException extends GHIOException { /** The message for this exception. */ private final String url; - /** - * Instantiates a new Http exception. - * - * @param connectorResponse - * the connector response to base this on - */ - public HttpException(GitHubConnectorResponse connectorResponse) { - this(GitHubResponse.getBodyAsStringOrNull(connectorResponse), - connectorResponse.statusCode(), - connectorResponse.header("Status"), - connectorResponse.request().url().toString()); - this.responseHeaderFields = connectorResponse.allHeaders(); - } - /** * Instantiates a new Http exception. * @@ -128,6 +114,20 @@ public HttpException(int responseCode, String responseMessage, @CheckForNull URL this(responseCode, responseMessage, url == null ? null : url.toString(), cause); } + /** + * Instantiates a new Http exception. + * + * @param connectorResponse + * the connector response to base this on + */ + public HttpException(GitHubConnectorResponse connectorResponse) { + this(GitHubResponse.getBodyAsStringOrNull(connectorResponse), + connectorResponse.statusCode(), + connectorResponse.header("Status"), + connectorResponse.request().url().toString()); + this.responseHeaderFields = connectorResponse.allHeaders(); + } + /** * Http response code of the request that cause the exception. * diff --git a/src/main/java/org/kohsuke/github/MarkdownMode.java b/src/main/java/org/kohsuke/github/MarkdownMode.java index 58245a93ba..35a9e41c04 100644 --- a/src/main/java/org/kohsuke/github/MarkdownMode.java +++ b/src/main/java/org/kohsuke/github/MarkdownMode.java @@ -11,17 +11,17 @@ * @see GHRepository#renderMarkdown(String, MarkdownMode) GHRepository#renderMarkdown(String, MarkdownMode) */ public enum MarkdownMode { + /** + * Render a document as plain Markdown, just like README files are rendered. + */ + MARKDOWN, /** * Render a document as user-content, e.g. like user comments or issues are rendered. In GFM mode, hard line breaks * are always taken into account, and issue and user mentions are linked accordingly. * * @see GHRepository#renderMarkdown(String, MarkdownMode) */ - GFM, - /** - * Render a document as plain Markdown, just like README files are rendered. - */ - MARKDOWN; + GFM; /** * To string. diff --git a/src/main/java/org/kohsuke/github/PagedIterable.java b/src/main/java/org/kohsuke/github/PagedIterable.java index a916af8009..7dc17aa0eb 100644 --- a/src/main/java/org/kohsuke/github/PagedIterable.java +++ b/src/main/java/org/kohsuke/github/PagedIterable.java @@ -32,6 +32,31 @@ public abstract class PagedIterable implements Iterable { public PagedIterable() { } + /** + * Sets the pagination size. + * + *

+ * When set to non-zero, each API call will retrieve this many entries. + * + * @param size + * the size + * @return the paged iterable + */ + public PagedIterable withPageSize(int size) { + this.pageSize = size; + return this; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Nonnull + public final PagedIterator iterator() { + return _iterator(pageSize); + } + /** * Iterator over page items. * @@ -43,13 +68,37 @@ public PagedIterable() { public abstract PagedIterator _iterator(int pageSize); /** - * Returns an iterator over elements of type {@code T}. + * Eagerly walk {@link PagedIterator} and return the result in an array. * - * @return an Iterator. + * @param iterator + * the {@link PagedIterator} to read + * @return an array of all elements from the {@link PagedIterator} + * @throws IOException + * if an I/O exception occurs. */ - @Nonnull - public final PagedIterator iterator() { - return _iterator(pageSize); + protected T[] toArray(final PagedIterator iterator) throws IOException { + try { + ArrayList pages = new ArrayList<>(); + int totalSize = 0; + T[] item; + do { + item = iterator.nextPageArray(); + totalSize += Array.getLength(item); + pages.add(item); + } while (iterator.hasNext()); + + Class type = (Class) item.getClass(); + + return concatenatePages(type, pages, totalSize); + } catch (GHException e) { + // if there was an exception inside the iterator it is wrapped as a GHException + // if the wrapped exception is an IOException, throw that + if (e.getCause() instanceof IOException) { + throw (IOException) e.getCause(); + } else { + throw e; + } + } } /** @@ -88,21 +137,6 @@ public Set toSet() throws IOException { return Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(this.toArray()))); } - /** - * Sets the pagination size. - * - *

- * When set to non-zero, each API call will retrieve this many entries. - * - * @param size - * the size - * @return the paged iterable - */ - public PagedIterable withPageSize(int size) { - this.pageSize = size; - return this; - } - /** * Concatenates a list of arrays into a single array. * @@ -128,38 +162,4 @@ private T[] concatenatePages(Class type, List pages, int totalLength) return result; } - /** - * Eagerly walk {@link PagedIterator} and return the result in an array. - * - * @param iterator - * the {@link PagedIterator} to read - * @return an array of all elements from the {@link PagedIterator} - * @throws IOException - * if an I/O exception occurs. - */ - protected T[] toArray(final PagedIterator iterator) throws IOException { - try { - ArrayList pages = new ArrayList<>(); - int totalSize = 0; - T[] item; - do { - item = iterator.nextPageArray(); - totalSize += Array.getLength(item); - pages.add(item); - } while (iterator.hasNext()); - - Class type = (Class) item.getClass(); - - return concatenatePages(type, pages, totalSize); - } catch (GHException e) { - // if there was an exception inside the iterator it is wrapped as a GHException - // if the wrapped exception is an IOException, throw that - if (e.getCause() instanceof IOException) { - throw (IOException) e.getCause(); - } else { - throw e; - } - } - } - } diff --git a/src/main/java/org/kohsuke/github/PagedIterator.java b/src/main/java/org/kohsuke/github/PagedIterator.java index ac6e54e826..73c8bf1a2d 100644 --- a/src/main/java/org/kohsuke/github/PagedIterator.java +++ b/src/main/java/org/kohsuke/github/PagedIterator.java @@ -26,6 +26,13 @@ */ public class PagedIterator implements Iterator { + /** The base. */ + @Nonnull + protected final Iterator base; + + @CheckForNull + private final Consumer itemInitializer; + /** * Current batch of items. Each time {@link #next()} is called the next item in this array will be returned. After * the last item of the array is returned, when {@link #next()} is called again, a new page of items will be fetched @@ -35,9 +42,6 @@ public class PagedIterator implements Iterator { */ private T[] currentPage; - @CheckForNull - private final Consumer itemInitializer; - /** * The index of the next item on the page, the item that will be returned when {@link #next()} is called. * @@ -45,10 +49,6 @@ public class PagedIterator implements Iterator { */ private int nextItemIndex; - /** The base. */ - @Nonnull - protected final Iterator base; - /** * Instantiates a new paged iterator. * @@ -62,6 +62,21 @@ public class PagedIterator implements Iterator { this.itemInitializer = itemInitializer; } + /** + * This poorly named method, initializes items with local data after they are fetched. It is up to the implementer + * to decide what local data to apply. + * + * @param page + * the page of items to be initialized + */ + protected void wrapUp(T[] page) { + if (itemInitializer != null) { + for (T item : page) { + itemInitializer.accept(item); + } + } + } + /** * {@inheritDoc} */ @@ -79,15 +94,6 @@ public T next() { return currentPage[nextItemIndex++]; } - /** - * Gets the next page worth of data. - * - * @return the list - */ - public List nextPage() { - return Arrays.asList(nextPageArray()); - } - /** * Fetch is called at the start of {@link #next()} or {@link #hasNext()} to fetch another page of data if it is * needed and available. @@ -117,18 +123,12 @@ private void fetch() { } /** - * This poorly named method, initializes items with local data after they are fetched. It is up to the implementer - * to decide what local data to apply. + * Gets the next page worth of data. * - * @param page - * the page of items to be initialized + * @return the list */ - protected void wrapUp(T[] page) { - if (itemInitializer != null) { - for (T item : page) { - itemInitializer.accept(item); - } - } + public List nextPage() { + return Arrays.asList(nextPageArray()); } /** diff --git a/src/main/java/org/kohsuke/github/PagedSearchIterable.java b/src/main/java/org/kohsuke/github/PagedSearchIterable.java index 8c6d00a26d..65f7442a2a 100644 --- a/src/main/java/org/kohsuke/github/PagedSearchIterable.java +++ b/src/main/java/org/kohsuke/github/PagedSearchIterable.java @@ -19,17 +19,17 @@ "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" }, justification = "Constructed by JSON API") public class PagedSearchIterable extends PagedIterable { - private final Class> receiverType; + private final transient GitHub root; private final GitHubRequest request; + private final Class> receiverType; + /** * As soon as we have any result fetched, it's set here so that we can report the total count. */ private SearchResult result; - private final transient GitHub root; - /** * Instantiates a new paged search iterable. * @@ -47,18 +47,15 @@ public class PagedSearchIterable extends PagedIterable { } /** - * Iterator. + * With page size. * - * @param pageSize - * the page size - * @return the paged iterator + * @param size + * the size + * @return the paged search iterable */ - @Nonnull @Override - public PagedIterator _iterator(int pageSize) { - final Iterator adapter = adapt( - GitHubPageIterator.create(root.getClient(), receiverType, request, pageSize)); - return new PagedIterator(adapter, null); + public PagedSearchIterable withPageSize(int size) { + return (PagedSearchIterable) super.withPageSize(size); } /** @@ -68,7 +65,7 @@ public PagedIterator _iterator(int pageSize) { */ public int getTotalCount() { populate(); - return result.totalCount; + return result.total_count; } /** @@ -78,24 +75,27 @@ public int getTotalCount() { */ public boolean isIncomplete() { populate(); - return result.incompleteResults; + return result.incomplete_results; + } + + private void populate() { + if (result == null) + iterator().hasNext(); } /** - * With page size. + * Iterator. * - * @param size - * the size - * @return the paged search iterable + * @param pageSize + * the page size + * @return the paged iterator */ + @Nonnull @Override - public PagedSearchIterable withPageSize(int size) { - return (PagedSearchIterable) super.withPageSize(size); - } - - private void populate() { - if (result == null) - iterator().hasNext(); + public PagedIterator _iterator(int pageSize) { + final Iterator adapter = adapt( + GitHubPageIterator.create(root.getClient(), receiverType, request, pageSize)); + return new PagedIterator(adapter, null); } /** diff --git a/src/main/java/org/kohsuke/github/RateLimitChecker.java b/src/main/java/org/kohsuke/github/RateLimitChecker.java index 15b5f0e58d..5b848cd17e 100644 --- a/src/main/java/org/kohsuke/github/RateLimitChecker.java +++ b/src/main/java/org/kohsuke/github/RateLimitChecker.java @@ -1,6 +1,5 @@ package org.kohsuke.github; -import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; @@ -24,58 +23,17 @@ public abstract class RateLimitChecker { /** - * A {@link RateLimitChecker} with a simple number as the limit. + * Create default RateLimitChecker instance */ - public static class LiteralValue extends RateLimitChecker { - private final int sleepAtOrBelow; - - /** - * Instantiates a new literal value. - * - * @param sleepAtOrBelow - * the sleep at or below - */ - public LiteralValue(int sleepAtOrBelow) { - if (sleepAtOrBelow < 0) { - // ignore negative numbers - sleepAtOrBelow = 0; - } - this.sleepAtOrBelow = sleepAtOrBelow; - } - - /** - * Check rate limit. - * - * @param record - * the record - * @param count - * the count - * @return true, if successful - * @throws InterruptedException - * the interrupted exception - */ - @Override - protected boolean checkRateLimit(GHRateLimit.Record record, long count) throws InterruptedException { - if (record.getRemaining() <= sleepAtOrBelow) { - return sleepUntilReset(record); - } - return false; - } - + public RateLimitChecker() { } + private static final Logger LOGGER = Logger.getLogger(RateLimitChecker.class.getName()); + /** The Constant NONE. */ public static final RateLimitChecker NONE = new RateLimitChecker() { }; - private static final Logger LOGGER = Logger.getLogger(RateLimitChecker.class.getName()); - - /** - * Create default RateLimitChecker instance - */ - public RateLimitChecker() { - } - /** * Decides whether the current request exceeds the allowed "rate limit" budget. If this determines the rate limit * will be exceeded, this method should sleep for some amount of time and must return {@code true}. Implementers are @@ -121,13 +79,13 @@ protected boolean checkRateLimit(GHRateLimit.Record rateLimitRecord, long count) */ protected final boolean sleepUntilReset(GHRateLimit.Record record) throws InterruptedException { // Sleep until reset - long sleepMilliseconds = record.getResetInstant().toEpochMilli() - System.currentTimeMillis(); + long sleepMilliseconds = record.getResetDate().getTime() - System.currentTimeMillis(); if (sleepMilliseconds > 0) { String message = String.format( "GitHub API - Current quota has %d remaining of %d. Waiting for quota to reset at %tT.", record.getRemaining(), record.getLimit(), - Date.from(record.getResetInstant())); + record.getResetDate()); LOGGER.log(Level.INFO, message); @@ -137,4 +95,45 @@ protected final boolean sleepUntilReset(GHRateLimit.Record record) throws Interr return false; } + /** + * A {@link RateLimitChecker} with a simple number as the limit. + */ + public static class LiteralValue extends RateLimitChecker { + private final int sleepAtOrBelow; + + /** + * Instantiates a new literal value. + * + * @param sleepAtOrBelow + * the sleep at or below + */ + public LiteralValue(int sleepAtOrBelow) { + if (sleepAtOrBelow < 0) { + // ignore negative numbers + sleepAtOrBelow = 0; + } + this.sleepAtOrBelow = sleepAtOrBelow; + } + + /** + * Check rate limit. + * + * @param record + * the record + * @param count + * the count + * @return true, if successful + * @throws InterruptedException + * the interrupted exception + */ + @Override + protected boolean checkRateLimit(GHRateLimit.Record record, long count) throws InterruptedException { + if (record.getRemaining() <= sleepAtOrBelow) { + return sleepUntilReset(record); + } + return false; + } + + } + } diff --git a/src/main/java/org/kohsuke/github/RateLimitTarget.java b/src/main/java/org/kohsuke/github/RateLimitTarget.java index 4f87995276..5fba008fed 100644 --- a/src/main/java/org/kohsuke/github/RateLimitTarget.java +++ b/src/main/java/org/kohsuke/github/RateLimitTarget.java @@ -12,6 +12,11 @@ public enum RateLimitTarget { */ CORE, + /** + * Selects or updates the {@link GHRateLimit#getSearch()} record. + */ + SEARCH, + /** * Selects or updates the {@link GHRateLimit#getGraphQL()} record. */ @@ -28,10 +33,5 @@ public enum RateLimitTarget { * This request uses no rate limit. If the response header includes rate limit information, it will apply to * {@link #CORE}. */ - NONE, - - /** - * Selects or updates the {@link GHRateLimit#getSearch()} record. - */ - SEARCH + NONE } diff --git a/src/main/java/org/kohsuke/github/Reactable.java b/src/main/java/org/kohsuke/github/Reactable.java index be7ab7b399..309f7d29b2 100644 --- a/src/main/java/org/kohsuke/github/Reactable.java +++ b/src/main/java/org/kohsuke/github/Reactable.java @@ -9,6 +9,13 @@ * @author Kohsuke Kawaguchi */ public interface Reactable { + /** + * List all the reactions left to this object. + * + * @return the paged iterable + */ + PagedIterable listReactions(); + /** * Leaves a reaction to this object. * @@ -29,11 +36,4 @@ public interface Reactable { * the io exception */ void deleteReaction(GHReaction reaction) throws IOException; - - /** - * List all the reactions left to this object. - * - * @return the paged iterable - */ - PagedIterable listReactions(); } diff --git a/src/main/java/org/kohsuke/github/ReactionContent.java b/src/main/java/org/kohsuke/github/ReactionContent.java index c0361d9b0a..15d3197d15 100644 --- a/src/main/java/org/kohsuke/github/ReactionContent.java +++ b/src/main/java/org/kohsuke/github/ReactionContent.java @@ -13,45 +13,29 @@ */ public enum ReactionContent { + /** The plus one. */ + PLUS_ONE("+1"), + + /** The minus one. */ + MINUS_ONE("-1"), + + /** The laugh. */ + LAUGH("laugh"), + /** The confused. */ CONFUSED("confused"), - /** The eyes. */ - EYES("eyes"), - /** The heart. */ HEART("heart"), /** The hooray. */ HOORAY("hooray"), - /** The laugh. */ - LAUGH("laugh"), - - /** The minus one. */ - MINUS_ONE("-1"), - - /** The plus one. */ - PLUS_ONE("+1"), - /** The rocket. */ - ROCKET("rocket"); + ROCKET("rocket"), - /** - * For content reaction content. - * - * @param content - * the content - * @return the reaction content - */ - @JsonCreator - public static ReactionContent forContent(String content) { - for (ReactionContent c : ReactionContent.values()) { - if (c.getContent().equals(content)) - return c; - } - return null; - } + /** The eyes. */ + EYES("eyes"); private final String content; @@ -74,4 +58,20 @@ public static ReactionContent forContent(String content) { public String getContent() { return content; } + + /** + * For content reaction content. + * + * @param content + * the content + * @return the reaction content + */ + @JsonCreator + public static ReactionContent forContent(String content) { + for (ReactionContent c : ReactionContent.values()) { + if (c.getContent().equals(content)) + return c; + } + return null; + } } diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 95f0366ebd..1e5e987657 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -27,7 +27,6 @@ import org.apache.commons.io.IOUtils; import org.kohsuke.github.connector.GitHubConnectorResponse; import org.kohsuke.github.function.InputStreamFunction; -import org.kohsuke.github.internal.graphql.response.GHGraphQLResponse; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -45,25 +44,6 @@ */ class Requester extends GitHubRequest.Builder { - /** - * Helper function to make it easy to pull streams. - * - * Copies an input stream to an in-memory input stream. The performance on this is not great but - * {@link GitHubConnectorResponse#bodyStream()} is closed at the end of every call to - * {@link GitHubClient#sendRequest(GitHubRequest, GitHubClient.BodyHandler)}, so any reads to the original input - * stream must be completed before then. There are a number of deprecated methods that return {@link InputStream}. - * This method keeps all of them using the same code path. - * - * @param inputStream - * the input stream to be copied - * @return an in-memory copy of the passed input stream - * @throws IOException - * if an error occurs while copying the stream - */ - @NonNull public static InputStream copyInputStream(InputStream inputStream) throws IOException { - return new ByteArrayInputStream(IOUtils.toByteArray(inputStream)); - } - /** The client. */ /* private */ final transient GitHubClient client; @@ -78,6 +58,18 @@ class Requester extends GitHubRequest.Builder { this.withApiUrl(client.getApiUrl()); } + /** + * Sends a request to the specified URL and checks that it is successful. + * + * @throws IOException + * the io exception + */ + public void send() throws IOException { + // Send expects there to be some body response, but doesn't care what it is. + // If there isn't a body, this will throw. + client.sendRequest(this, (connectorResponse) -> GitHubResponse.getBodyAsString(connectorResponse)); + } + /** * Sends a request and parses the response into the given type via databinding. * @@ -85,7 +77,7 @@ class Requester extends GitHubRequest.Builder { * the type parameter * @param type * the type - * @return an instance of {@code T} + * @return an instance of {@link T} * @throws IOException * if the server returns 4xx/5xx responses. */ @@ -95,24 +87,20 @@ public T fetch(@Nonnull Class type) throws IOException { } /** - * Sends a request and parses the response into the given type via databinding in GraphQL response. + * Like {@link #fetch(Class)} but updates an existing object instead of creating a new instance. * * @param * the type parameter - * @param type - * the type - * @return an instance of {@code GHGraphQLResponse} + * @param existingInstance + * the existing instance + * @return the updated instance * @throws IOException - * if the server returns 4xx/5xx responses. + * the io exception */ - public , S> S fetchGraphQL(@Nonnull Class type) throws IOException { - T response = fetch(type); - - if (!response.isSuccessful()) { - throw new IOException("GraphQL request failed by:" + response.getErrorMessages()); - } - - return response.getData(); + public T fetchInto(@Nonnull T existingInstance) throws IOException { + return client + .sendRequest(this, (connectorResponse) -> GitHubResponse.parseBody(connectorResponse, existingInstance)) + .body(); } /** @@ -127,23 +115,6 @@ public int fetchHttpStatusCode() throws IOException { return client.sendRequest(build(), null).statusCode(); } - /** - * Like {@link #fetch(Class)} but updates an existing object instead of creating a new instance. - * - * @param - * the type parameter - * @param existingInstance - * the existing instance - * @return the updated instance - * @throws IOException - * the io exception - */ - public T fetchInto(@Nonnull T existingInstance) throws IOException { - return client - .sendRequest(this, (connectorResponse) -> GitHubResponse.parseBody(connectorResponse, existingInstance)) - .body(); - } - /** * Response input stream. There are scenarios where direct stream reading is needed, however it is better to use * {@link #fetch(Class)} where possible. @@ -161,29 +132,27 @@ public T fetchStream(@Nonnull InputStreamFunction handler) throws IOExcep } /** - * Sends a request to the specified URL and checks that it is successful. + * Helper function to make it easy to pull streams. * - * @throws IOException - * the io exception - */ - public void send() throws IOException { - // Send expects there to be some body response, but doesn't care what it is. - // If there isn't a body, this will throw. - client.sendRequest(this, (connectorResponse) -> GitHubResponse.getBodyAsString(connectorResponse)); - } - - /** - * Sends a GraphQL request with no response + * Copies an input stream to an in-memory input stream. The performance on this is not great but + * {@link GitHubConnectorResponse#bodyStream()} is closed at the end of every call to + * {@link GitHubClient#sendRequest(GitHubRequest, GitHubClient.BodyHandler)}, so any reads to the original input + * stream must be completed before then. There are a number of deprecated methods that return {@link InputStream}. + * This method keeps all of them using the same code path. * + * @param inputStream + * the input stream to be copied + * @return an in-memory copy of the passed input stream * @throws IOException - * the io exception + * if an error occurs while copying the stream */ - public void sendGraphQL() throws IOException { - fetchGraphQL(GHGraphQLResponse.ObjectResponse.class); + @NonNull + public static InputStream copyInputStream(InputStream inputStream) throws IOException { + return new ByteArrayInputStream(IOUtils.toByteArray(inputStream)); } /** - * Creates {@link PagedIterable } from this builder using the provided {@link Consumer}{@code }. + * Creates {@link PagedIterable } from this builder using the provided {@link Consumer}. *

* This method and the {@link PagedIterable } do not actually begin fetching data until {@link Iterator#next()} * or {@link Iterator#hasNext()} are called. diff --git a/src/main/java/org/kohsuke/github/SearchResult.java b/src/main/java/org/kohsuke/github/SearchResult.java index fe7e350439..ca2f621df7 100644 --- a/src/main/java/org/kohsuke/github/SearchResult.java +++ b/src/main/java/org/kohsuke/github/SearchResult.java @@ -10,11 +10,11 @@ */ abstract class SearchResult { - /** The incomplete results. */ - boolean incompleteResults; - /** The total count. */ - int totalCount; + int total_count; + + /** The incomplete results. */ + boolean incomplete_results; /** * Wraps up the retrieved object and return them. Only called once. diff --git a/src/main/java/org/kohsuke/github/authorization/AppInstallationAuthorizationProvider.java b/src/main/java/org/kohsuke/github/authorization/AppInstallationAuthorizationProvider.java index 112a0b727c..7ad33ede46 100644 --- a/src/main/java/org/kohsuke/github/authorization/AppInstallationAuthorizationProvider.java +++ b/src/main/java/org/kohsuke/github/authorization/AppInstallationAuthorizationProvider.java @@ -7,8 +7,8 @@ import org.kohsuke.github.GitHub; import java.io.IOException; +import java.time.Duration; import java.time.Instant; -import java.time.temporal.ChronoUnit; import java.util.Objects; import javax.annotation.Nonnull; @@ -18,23 +18,6 @@ */ public class AppInstallationAuthorizationProvider extends GitHub.DependentAuthorizationProvider { - /** - * Provides an interface that returns an app to be used by an AppInstallationAuthorizationProvider - */ - @FunctionalInterface - public interface AppInstallationProvider { - /** - * Provides a GHAppInstallation for the given GHApp - * - * @param app - * The GHApp to use - * @return The GHAppInstallation - * @throws IOException - * on error - */ - GHAppInstallation getAppInstallation(GHApp app) throws IOException; - } - private final AppInstallationProvider appInstallationProvider; private String authorization; @@ -74,7 +57,24 @@ private String refreshToken() throws IOException { GitHub gitHub = this.gitHub(); GHAppInstallation installationByOrganization = appInstallationProvider.getAppInstallation(gitHub.getApp()); GHAppInstallationToken ghAppInstallationToken = installationByOrganization.createToken().create(); - this.validUntil = ghAppInstallationToken.getExpiresAt().minus(5, ChronoUnit.MINUTES); + this.validUntil = ghAppInstallationToken.getExpiresAt().toInstant().minus(Duration.ofMinutes(5)); return Objects.requireNonNull(ghAppInstallationToken.getToken()); } + + /** + * Provides an interface that returns an app to be used by an AppInstallationAuthorizationProvider + */ + @FunctionalInterface + public interface AppInstallationProvider { + /** + * Provides a GHAppInstallation for the given GHApp + * + * @param app + * The GHApp to use + * @return The GHAppInstallation + * @throws IOException + * on error + */ + GHAppInstallation getAppInstallation(GHApp app) throws IOException; + } } diff --git a/src/main/java/org/kohsuke/github/authorization/ImmutableAuthorizationProvider.java b/src/main/java/org/kohsuke/github/authorization/ImmutableAuthorizationProvider.java index e236d1c66e..09ee6ae467 100644 --- a/src/main/java/org/kohsuke/github/authorization/ImmutableAuthorizationProvider.java +++ b/src/main/java/org/kohsuke/github/authorization/ImmutableAuthorizationProvider.java @@ -7,53 +7,16 @@ */ public class ImmutableAuthorizationProvider implements AuthorizationProvider { - /** - * An internal class representing all user-related credentials, which are credentials that have a login or should - * query the user endpoint for the login matching this credential. - * - * @see org.kohsuke.github.authorization.UserAuthorizationProvider UserAuthorizationProvider - */ - private static class UserProvider extends ImmutableAuthorizationProvider implements UserAuthorizationProvider { - - private final String login; - - UserProvider(String authorization) { - this(authorization, null); - } - - UserProvider(String authorization, String login) { - super(authorization); - this.login = login; - } - - @CheckForNull - @Override - public String getLogin() { - return login; - } - - } - - /** - * Builds and returns a {@link AuthorizationProvider} from a given App Installation Token - * - * @param appInstallationToken - * A string containing the GitHub App installation token - * @return the configured Builder from given GitHub App installation token. - */ - public static AuthorizationProvider fromAppInstallationToken(String appInstallationToken) { - return fromOauthToken(appInstallationToken, ""); - } + private final String authorization; /** - * Builds and returns a {@link AuthorizationProvider} from a given jwtToken + * ImmutableAuthorizationProvider constructor * - * @param jwtToken - * The JWT token - * @return a correctly configured {@link AuthorizationProvider} that will always return the same provided jwtToken + * @param authorization + * the authorization string */ - public static AuthorizationProvider fromJwtToken(String jwtToken) { - return new ImmutableAuthorizationProvider(String.format("Bearer %s", jwtToken)); + public ImmutableAuthorizationProvider(String authorization) { + this.authorization = authorization; } /** @@ -83,20 +46,57 @@ public static AuthorizationProvider fromOauthToken(String oauthAccessToken, Stri return new UserProvider(String.format("token %s", oauthAccessToken), login); } - private final String authorization; + /** + * Builds and returns a {@link AuthorizationProvider} from a given App Installation Token + * + * @param appInstallationToken + * A string containing the GitHub App installation token + * @return the configured Builder from given GitHub App installation token. + */ + public static AuthorizationProvider fromAppInstallationToken(String appInstallationToken) { + return fromOauthToken(appInstallationToken, ""); + } /** - * ImmutableAuthorizationProvider constructor + * Builds and returns a {@link AuthorizationProvider} from a given jwtToken * - * @param authorization - * the authorization string + * @param jwtToken + * The JWT token + * @return a correctly configured {@link AuthorizationProvider} that will always return the same provided jwtToken */ - public ImmutableAuthorizationProvider(String authorization) { - this.authorization = authorization; + public static AuthorizationProvider fromJwtToken(String jwtToken) { + return new ImmutableAuthorizationProvider(String.format("Bearer %s", jwtToken)); } @Override public String getEncodedAuthorization() { return this.authorization; } + + /** + * An internal class representing all user-related credentials, which are credentials that have a login or should + * query the user endpoint for the login matching this credential. + * + * @see org.kohsuke.github.authorization.UserAuthorizationProvider UserAuthorizationProvider + */ + private static class UserProvider extends ImmutableAuthorizationProvider implements UserAuthorizationProvider { + + private final String login; + + UserProvider(String authorization) { + this(authorization, null); + } + + UserProvider(String authorization, String login) { + super(authorization); + this.login = login; + } + + @CheckForNull + @Override + public String getLogin() { + return login; + } + + } } diff --git a/src/main/java/org/kohsuke/github/connector/GitHubConnector.java b/src/main/java/org/kohsuke/github/connector/GitHubConnector.java index 94df7869f4..a9f2f1da1e 100644 --- a/src/main/java/org/kohsuke/github/connector/GitHubConnector.java +++ b/src/main/java/org/kohsuke/github/connector/GitHubConnector.java @@ -13,6 +13,25 @@ @FunctionalInterface public interface GitHubConnector { + /** + * Sends a request and retrieves a raw response for processing. + * + * Implementers of {@link GitHubConnector#send(GitHubConnectorRequest)} process the information from a + * {@link GitHubConnectorRequest} to open an HTTP connection and retrieve a raw response. They then return a class + * that extends {@link GitHubConnectorResponse} corresponding their response data. + * + * Clients should not implement their own {@link GitHubConnectorRequest}. The {@link GitHubConnectorRequest} + * provided by the caller of {@link GitHubConnector#send(GitHubConnectorRequest)} should be passed to the + * constructor of {@link GitHubConnectorResponse}. + * + * @param connectorRequest + * the request data to be sent. + * @return a GitHubConnectorResponse for the request + * @throws IOException + * if there is an I/O error + */ + GitHubConnectorResponse send(GitHubConnectorRequest connectorRequest) throws IOException; + /** * Default implementation used when connector is not set by user. * @@ -32,23 +51,4 @@ public GitHubConnectorResponse send(GitHubConnectorRequest connectorRequest) thr throw new GHIOException("Offline"); } }; - - /** - * Sends a request and retrieves a raw response for processing. - * - * Implementers of {@link GitHubConnector#send(GitHubConnectorRequest)} process the information from a - * {@link GitHubConnectorRequest} to open an HTTP connection and retrieve a raw response. They then return a class - * that extends {@link GitHubConnectorResponse} corresponding their response data. - * - * Clients should not implement their own {@link GitHubConnectorRequest}. The {@link GitHubConnectorRequest} - * provided by the caller of {@link GitHubConnector#send(GitHubConnectorRequest)} should be passed to the - * constructor of {@link GitHubConnectorResponse}. - * - * @param connectorRequest - * the request data to be sent. - * @return a GitHubConnectorResponse for the request - * @throws IOException - * if there is an I/O error - */ - GitHubConnectorResponse send(GitHubConnectorRequest connectorRequest) throws IOException; } diff --git a/src/main/java/org/kohsuke/github/connector/GitHubConnectorRequest.java b/src/main/java/org/kohsuke/github/connector/GitHubConnectorRequest.java index 59edf79dc5..e00d59dcec 100644 --- a/src/main/java/org/kohsuke/github/connector/GitHubConnectorRequest.java +++ b/src/main/java/org/kohsuke/github/connector/GitHubConnectorRequest.java @@ -23,6 +23,16 @@ */ public interface GitHubConnectorRequest { + /** + * The request method for this request. + * + * For example, {@code GET} or {@code PATCH}. + * + * @return the request method. + */ + @Nonnull + String method(); + /** * All request headers for this request. * @@ -32,12 +42,14 @@ public interface GitHubConnectorRequest { Map> allHeaders(); /** - * Gets the request body as an InputStream. + * Gets the value contained in a header field. * - * @return the request body as an InputStream. + * @param name + * the name of the field. + * @return the value contained in that field, or {@code null} if not present. */ @CheckForNull - InputStream body(); + String header(String name); /** * Get the content type for the body of this request. @@ -48,37 +60,25 @@ public interface GitHubConnectorRequest { String contentType(); /** - * Gets whether the request has information in {@link #body()} that needs to be sent. - * - * @return true, if the body is not null. Otherwise, false. - */ - boolean hasBody(); - - /** - * Gets the value contained in a header field. + * Gets the request body as an InputStream. * - * @param name - * the name of the field. - * @return the value contained in that field, or {@code null} if not present. + * @return the request body as an InputStream. */ @CheckForNull - String header(String name); + InputStream body(); /** - * The request method for this request. - * - * For example, {@code GET} or {@code PATCH}. + * Gets the url for this request. * - * @return the request method. + * @return the url for this request. */ @Nonnull - String method(); + URL url(); /** - * Gets the url for this request. + * Gets whether the request has information in {@link #body()} that needs to be sent. * - * @return the url for this request. + * @return true, if the body is not null. Otherwise, false. */ - @Nonnull - URL url(); + boolean hasBody(); } diff --git a/src/main/java/org/kohsuke/github/connector/GitHubConnectorResponse.java b/src/main/java/org/kohsuke/github/connector/GitHubConnectorResponse.java index a17e3a4e92..b71fc8abc5 100644 --- a/src/main/java/org/kohsuke/github/connector/GitHubConnectorResponse.java +++ b/src/main/java/org/kohsuke/github/connector/GitHubConnectorResponse.java @@ -7,25 +7,15 @@ import java.io.Closeable; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; +import java.util.*; import java.util.zip.GZIPInputStream; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; -import static java.net.HttpURLConnection.HTTP_OK; - /** * Response information supplied when a response is received and before the body is processed. *

- * During a request to GitHub, {@link GitHubConnector#send(GitHubConnectorRequest)} returns a - * {@link GitHubConnectorResponse}. This is processed to create a GitHubResponse. - *

* Instances of this class are closed once the response is done being processed. This means that {@link #bodyStream()} * will not be readable after a call is completed. * @@ -36,45 +26,15 @@ */ public abstract class GitHubConnectorResponse implements Closeable { - /** - * A ByteArrayResponse class - * - * @deprecated Inherit directly from {@link GitHubConnectorResponse}. - */ - @Deprecated - public abstract static class ByteArrayResponse extends GitHubConnectorResponse { - - /** - * Constructor for ByteArray Response - * - * @param request - * the request - * @param statusCode - * the status code - * @param headers - * the headers - */ - protected ByteArrayResponse(@Nonnull GitHubConnectorRequest request, - int statusCode, - @Nonnull Map> headers) { - super(request, statusCode, headers); - } - } - private static final Comparator nullableCaseInsensitiveComparator = Comparator .nullsFirst(String.CASE_INSENSITIVE_ORDER); - private byte[] bodyBytes = null; - private InputStream bodyStream = null; - private boolean bodyStreamCalled = false; - @Nonnull - private final Map> headers; - private boolean isBodyStreamRereadable; - private boolean isClosed = false; + private final int statusCode; + @Nonnull private final GitHubConnectorRequest request; - - private final int statusCode; + @Nonnull + private final Map> headers; /** * GitHubConnectorResponse constructor @@ -98,79 +58,6 @@ protected GitHubConnectorResponse(@Nonnull GitHubConnectorRequest request, caseInsensitiveMap.put(entry.getKey(), Collections.unmodifiableList(new ArrayList<>(entry.getValue()))); } this.headers = Collections.unmodifiableMap(caseInsensitiveMap); - this.isBodyStreamRereadable = false; - } - - /** - * The headers for this response. - * - * @return the headers for this response. - */ - @Nonnull - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable map of unmodifiable lists") - public Map> allHeaders() { - return headers; - } - - /** - * The response body as an {@link InputStream}. - * - * When {@link #isBodyStreamRereadable} is false, {@link #bodyStream()} can only be called once and the returned - * stream should be assumed to be read-once and not resetable. This is the default behavior for HTTP_OK responses - * and significantly reduces memory usage. - * - * When {@link #isBodyStreamRereadable} is true, {@link #bodyStream()} can be called be called multiple times. The - * full stream data is read into a byte array during the first call. Each call returns a new stream backed by the - * same byte array. This uses more memory, but is required to enable rereading the body stream during trace logging, - * debugging, and error responses. - * - * @return the response body - * @throws IOException - * if response stream is null or an I/O Exception occurs. - */ - @Nonnull - public InputStream bodyStream() throws IOException { - synchronized (this) { - if (isClosed) { - throw new IOException("Response is closed"); - } - - if (bodyStreamCalled) { - if (!isBodyStreamRereadable()) { - throw new IOException("Response body not rereadable"); - } - } else { - bodyStream = wrapStream(rawBodyStream()); - bodyStreamCalled = true; - } - - if (bodyStream == null) { - throw new IOException("Response body missing, stream null"); - } else if (!isBodyStreamRereadable()) { - return bodyStream; - } - - // Load rereadable byte array - if (bodyBytes == null) { - bodyBytes = IOUtils.toByteArray(bodyStream); - // Close the raw body stream after successfully reading - IOUtils.closeQuietly(bodyStream); - } - - return new ByteArrayInputStream(bodyBytes); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void close() throws IOException { - synchronized (this) { - IOUtils.closeQuietly(bodyStream); - isClosed = true; - this.bodyBytes = null; - } } /** @@ -190,71 +77,25 @@ public String header(String name) { } /** - * The body stream rereadable state. - * - * Body stream defaults to read once for HTTP_OK responses (to reduce memory usage). For non-HTTP_OK responses, body - * stream is switched to rereadable (in-memory byte array) for error processing. - * - * Calling {@link #setBodyStreamRereadable()} will force {@link #isBodyStreamRereadable} to be true for this - * response regardless of {@link #statusCode} value. - * - * @return true when body stream is rereadable. - */ - public boolean isBodyStreamRereadable() { - synchronized (this) { - return isBodyStreamRereadable || statusCode != HTTP_OK; - } - } - - /** - * Parse a header value as a signed decimal integer. + * The response body as an {@link InputStream}. * - * @param name - * the header field to parse - * @return integer value of the header field - * @throws NumberFormatException - * if the header is missing or does not contain a parsable integer. + * @return the response body + * @throws IOException + * if response stream is null or an I/O Exception occurs. */ - public final int parseInt(String name) throws NumberFormatException { - try { - String headerValue = header(name); - return Integer.parseInt(headerValue); - } catch (NumberFormatException e) { - throw new NumberFormatException(name + ": " + e.getMessage()); - } - } + @Nonnull + public abstract InputStream bodyStream() throws IOException; /** - * Gets the {@link GitHubConnector} for this response. + * Gets the {@link GitHubConnectorRequest} for this response. * - * @return the {@link GitHubConnector} for this response. + * @return the {@link GitHubConnectorRequest} for this response. */ @Nonnull public GitHubConnectorRequest request() { return request; } - /** - * Force body stream to rereadable regardless of status code. - * - * Calling {@link #setBodyStreamRereadable()} will force {@link #isBodyStreamRereadable} to be true for this - * response regardless of {@link #statusCode} value. - * - * This is required to support body value logging during low-level tracing but should be avoided in general since it - * consumes significantly more memory. - * - * Will throw runtime exception if a non-rereadable body stream has already been returned from - * {@link #bodyStream()}. - */ - public void setBodyStreamRereadable() { - synchronized (this) { - if (bodyStreamCalled && !isBodyStreamRereadable()) { - throw new RuntimeException("bodyStream() already called in read-once mode"); - } - isBodyStreamRereadable = true; - } - } - /** * The status code for this response. * @@ -265,20 +106,15 @@ public int statusCode() { } /** - * Get the raw implementation specific body stream for this response. - * - * This method will only be called once to completion. If an exception is thrown by this method, it may be called - * multiple times. - * - * The stream returned from this method will be closed when the response is closed or sooner. Inheriting classes do - * not need to close it. + * The headers for this response. * - * @return the stream for the raw response - * @throws IOException - * if an I/O Exception occurs. + * @return the headers for this response. */ - @CheckForNull - protected abstract InputStream rawBodyStream() throws IOException; + @Nonnull + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable map of unmodifiable lists") + public Map> allHeaders() { + return headers; + } /** * Handles wrapping the body stream if indicated by the "Content-Encoding" header. @@ -298,4 +134,95 @@ protected InputStream wrapStream(InputStream stream) throws IOException { throw new UnsupportedOperationException("Unexpected Content-Encoding: " + encoding); } + + /** + * Parse a header value as a signed decimal integer. + * + * @param name + * the header field to parse + * @return integer value of the header field + * @throws NumberFormatException + * if the header is missing or does not contain a parsable integer. + */ + public final int parseInt(String name) throws NumberFormatException { + try { + String headerValue = header(name); + return Integer.parseInt(headerValue); + } catch (NumberFormatException e) { + throw new NumberFormatException(name + ": " + e.getMessage()); + } + } + + /** + * A ByteArrayResponse class + */ + public abstract static class ByteArrayResponse extends GitHubConnectorResponse { + + private boolean inputStreamRead = false; + private byte[] inputBytes = null; + private boolean isClosed = false; + + /** + * Constructor for ByteArray Response + * + * @param request + * the request + * @param statusCode + * the status code + * @param headers + * the headers + */ + protected ByteArrayResponse(@Nonnull GitHubConnectorRequest request, + int statusCode, + @Nonnull Map> headers) { + super(request, statusCode, headers); + } + + /** + * {@inheritDoc} + */ + @Override + @Nonnull + public InputStream bodyStream() throws IOException { + if (isClosed) { + throw new IOException("Response is closed"); + } + synchronized (this) { + if (!inputStreamRead) { + InputStream rawStream = rawBodyStream(); + try (InputStream stream = wrapStream(rawStream)) { + if (stream != null) { + inputBytes = IOUtils.toByteArray(stream); + } + } + inputStreamRead = true; + } + } + + if (inputBytes == null) { + throw new IOException("Response body missing, stream null"); + } + + return new ByteArrayInputStream(inputBytes); + } + + /** + * Get the raw implementation specific body stream for this response. + * + * This method will only be called once to completion. If an exception is thrown, it may be called multiple + * times. + * + * @return the stream for the raw response + * @throws IOException + * if an I/O Exception occurs. + */ + @CheckForNull + protected abstract InputStream rawBodyStream() throws IOException; + + @Override + public void close() throws IOException { + isClosed = true; + this.inputBytes = null; + } + } } diff --git a/src/main/java/org/kohsuke/github/example/dataobject/ReadOnlyObjects.java b/src/main/java/org/kohsuke/github/example/dataobject/ReadOnlyObjects.java index 8a0b8dbb4b..d9b0f0e2a7 100644 --- a/src/main/java/org/kohsuke/github/example/dataobject/ReadOnlyObjects.java +++ b/src/main/java/org/kohsuke/github/example/dataobject/ReadOnlyObjects.java @@ -31,6 +31,12 @@ */ public final class ReadOnlyObjects { + /** + * Placeholder constructor. + */ + public ReadOnlyObjects() { + } + /** * All GHMeta data objects should expose these values. * @@ -38,11 +44,18 @@ public final class ReadOnlyObjects { */ public interface GHMetaExample { /** - * Gets api. + * Is verifiable password authentication boolean. * - * @return the api + * @return the boolean */ - List getApi(); + boolean isVerifiablePasswordAuthentication(); + + /** + * Gets hooks. + * + * @return the hooks + */ + List getHooks(); /** * Gets git. @@ -52,18 +65,18 @@ public interface GHMetaExample { List getGit(); /** - * Gets hooks. + * Gets web. * - * @return the hooks + * @return the web */ - List getHooks(); + List getWeb(); /** - * Gets importer. + * Gets api. * - * @return the importer + * @return the api */ - List getImporter(); + List getApi(); /** * Gets pages. @@ -73,190 +86,300 @@ public interface GHMetaExample { List getPages(); /** - * Gets web. - * - * @return the web - */ - List getWeb(); - - /** - * Is verifiable password authentication boolean. + * Gets importer. * - * @return the boolean + * @return the importer */ - boolean isVerifiablePasswordAuthentication(); + List getImporter(); } /** - * This version uses only public getters and returns unmodifiable lists and has final fields + * This version uses public getters and setters and leaves it up to Jackson how it wants to fill them. *

* Pro: *

    - *
  • Moderate amount of code
  • - *
  • More annotations
  • - *
  • Fields final and lists unmodifiable
  • + *
  • Easy to create
  • + *
  • Not much code
  • + *
  • Minimal annotations
  • *
* Con: *
    - *
  • Extra allocations - default array lists will be replaced by Jackson (yes, even though they are final)
  • - *
  • Added constructor is annoying
  • - *
  • If this object could be refreshed or populated, then the final is misleading (and possibly buggy)
  • + *
  • Exposes public setters for fields that should not be changed, flagged by spotbugs
  • + *
  • Lists modifiable when they should not be changed
  • + *
  • Jackson generally doesn't call the setters, it just sets the fields directly
  • *
* - * @author Liam Newman + * @author Paulo Miguel Almeida * @see org.kohsuke.github.GHMeta */ - public static class GHMetaGettersFinal implements GHMetaExample { + public static class GHMetaPublic implements GHMetaExample { - private final List api = new ArrayList<>(); - private final List git = new ArrayList<>(); - private final List hooks = new ArrayList<>(); - private final List importer = new ArrayList<>(); - private final List pages = new ArrayList<>(); - private final boolean verifiablePasswordAuthentication; - private final List web = new ArrayList<>(); + /** + * Create default GHMetaPublic instance + */ + public GHMetaPublic() { + } - @JsonCreator - private GHMetaGettersFinal( - @JsonProperty("verifiable_password_authentication") boolean verifiablePasswordAuthentication) { - // boolean fields when final seem to be really final, so we have to switch to constructor + @JsonProperty("verifiable_password_authentication") + private boolean verifiablePasswordAuthentication; + private List hooks; + private List git; + private List web; + private List api; + private List pages; + private List importer; + + public boolean isVerifiablePasswordAuthentication() { + return verifiablePasswordAuthentication; + } + + /** + * Sets verifiable password authentication. + * + * @param verifiablePasswordAuthentication + * the verifiable password authentication + */ + public void setVerifiablePasswordAuthentication(boolean verifiablePasswordAuthentication) { this.verifiablePasswordAuthentication = verifiablePasswordAuthentication; } - public List getApi() { - return Collections.unmodifiableList(api); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + public List getHooks() { + return hooks; + } + + /** + * Sets hooks. + * + * @param hooks + * the hooks + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") + public void setHooks(List hooks) { + this.hooks = hooks; } + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") public List getGit() { - return Collections.unmodifiableList(git); + return git; } - public List getHooks() { - return Collections.unmodifiableList(hooks); + /** + * Sets git. + * + * @param git + * the git + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") + public void setGit(List git) { + this.git = git; } - public List getImporter() { - return Collections.unmodifiableList(importer); + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + public List getWeb() { + return web; + } + + /** + * Sets web. + * + * @param web + * the web + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") + public void setWeb(List web) { + this.web = web; + } + + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + public List getApi() { + return api; + } + + /** + * Sets api. + * + * @param api + * the api + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") + public void setApi(List api) { + this.api = api; } + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") public List getPages() { - return Collections.unmodifiableList(pages); + return pages; } - public List getWeb() { - return Collections.unmodifiableList(web); + /** + * Sets pages. + * + * @param pages + * the pages + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") + public void setPages(List pages) { + this.pages = pages; } - public boolean isVerifiablePasswordAuthentication() { - return verifiablePasswordAuthentication; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + public List getImporter() { + return importer; + } + + /** + * Sets importer. + * + * @param importer + * the importer + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") + public void setImporter(List importer) { + this.importer = importer; } + } /** - * This version uses only public getters and returns unmodifiable lists + * This version uses public getters and shows that package or private setters both can be used by jackson. You can + * check this by running in debug and setting break points in the setters. + * *

* Pro: *

    - *
  • Fields final and lists unmodifiable
  • - *
  • Construction behavior can be controlled - if values depended on each other or needed to be set in a specific - * order, this could do that.
  • - *
  • JsonProrperty "required" works on JsonCreator constructors - lets annotation define required values
  • + *
  • Easy to create
  • + *
  • Not much code
  • + *
  • Some annotations
  • *
* Con: *
    - *
  • There is no way you'd know about this without some research
  • - *
  • Specific annotations needed
  • - *
  • Nonnull annotations are misleading - null value is not checked even for "required" constructor - * parameters
  • - *
  • Brittle and verbose - not friendly to large number of fields
  • + *
  • Exposes some package setters for fields that should not be changed, better than public
  • + *
  • Lists modifiable when they should not be changed
  • *
* * @author Liam Newman * @see org.kohsuke.github.GHMeta */ - public static class GHMetaGettersFinalCreator implements GHMetaExample { - - private final List api; - private final List git; - private final List hooks; - private final List importer; - private final List pages; - private final boolean verifiablePasswordAuthentication; - private final List web; + public static class GHMetaPackage implements GHMetaExample { /** - * - * @param hooks - * the hooks - required property works, but only on creator json properties like this, ignores - * Nonnull, checked manually - * @param git - * the git list - required property works, but only on creator json properties like this, misleading - * Nonnull annotation - * @param web - * the web list - misleading Nonnull annotation - * @param api - * the api list - misleading Nonnull annotation - * @param pages - * the pages list - misleading Nonnull annotation - * @param importer - * the importer list - misleading Nonnull annotation - * @param verifiablePasswordAuthentication - * true or false + * Create default GHMetaPackage instance */ - @JsonCreator - private GHMetaGettersFinalCreator(@Nonnull @JsonProperty(value = "hooks", required = true) List hooks, - @Nonnull @JsonProperty(value = "git", required = true) List git, - @Nonnull @JsonProperty("web") List web, - @Nonnull @JsonProperty("api") List api, - @Nonnull @JsonProperty("pages") List pages, - @Nonnull @JsonProperty("importer") List importer, - @JsonProperty("verifiable_password_authentication") boolean verifiablePasswordAuthentication) { + public GHMetaPackage() { + } - // to ensure a value is actually not null we still have to do a null check - Objects.requireNonNull(hooks); + private boolean verifiablePasswordAuthentication; + private List hooks; + private List git; + private List web; + private List api; + private List pages; - this.verifiablePasswordAuthentication = verifiablePasswordAuthentication; - this.hooks = Collections.unmodifiableList(hooks); - this.git = Collections.unmodifiableList(git); - this.web = Collections.unmodifiableList(web); - this.api = Collections.unmodifiableList(api); - this.pages = Collections.unmodifiableList(pages); - this.importer = Collections.unmodifiableList(importer); + /** + * Missing {@link JsonProperty} or having it on the field will cause Jackson to ignore getters and setters. + */ + @JsonProperty + private List importer; + + @JsonProperty("verifiable_password_authentication") + public boolean isVerifiablePasswordAuthentication() { + return verifiablePasswordAuthentication; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") - public List getApi() { - return api; + private void setVerifiablePasswordAuthentication(boolean verifiablePasswordAuthentication) { + this.verifiablePasswordAuthentication = verifiablePasswordAuthentication; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") + @JsonProperty + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + public List getHooks() { + return hooks; + } + + /** + * Setters can be private (or package local) and will still be called by Jackson. The {@link JsonProperty} can + * got on the getter or setter and still work. + * + * @param hooks + * list of hooks + */ + private void setHooks(List hooks) { + this.hooks = hooks; + } + + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") public List getGit() { return git; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") - public List getHooks() { - return hooks; + /** + * Since we mostly use Jackson for deserialization, {@link JsonSetter} is also okay, but {@link JsonProperty} is + * preferred. + * + * @param git + * list of git addresses + */ + @JsonSetter + void setGit(List git) { + this.git = git; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") - public List getImporter() { - return importer; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + public List getWeb() { + return web; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") + /** + * The {@link JsonProperty} can got on the getter or setter and still work. + * + * @param web + * list of web addresses + */ + void setWeb(List web) { + this.web = web; + } + + @JsonProperty + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + public List getApi() { + return api; + } + + void setApi(List api) { + this.api = api; + } + + @JsonProperty + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") public List getPages() { return pages; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") - public List getWeb() { - return web; + void setPages(List pages) { + this.pages = pages; } - public boolean isVerifiablePasswordAuthentication() { - return verifiablePasswordAuthentication; + /** + * Missing {@link JsonProperty} or having it on the field will cause Jackson to ignore getters and setters. + * + * @return list of importer addresses + */ + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + public List getImporter() { + return importer; } + + /** + * Missing {@link JsonProperty} or having it on the field will cause Jackson to ignore getters and setters. + * + * @param importer + * list of importer addresses + */ + void setImporter(List importer) { + this.importer = importer; + } + } /** @@ -283,345 +406,222 @@ public boolean isVerifiablePasswordAuthentication() { */ public static class GHMetaGettersUnmodifiable implements GHMetaExample { - private List api; - - private List git; - private List hooks; /** - * If this were an optional member, we could fill it with an empty list by default. + * Create default GHMetaGettersUnmodifiable instance */ - private List importer = new ArrayList<>(); - private List pages; + public GHMetaGettersUnmodifiable() { + } + @JsonProperty("verifiable_password_authentication") private boolean verifiablePasswordAuthentication; + private List hooks; + private List git; private List web; + private List api; + private List pages; /** - * Create default GHMetaGettersUnmodifiable instance + * If this were an optional member, we could fill it with an empty list by default. */ - public GHMetaGettersUnmodifiable() { + private List importer = new ArrayList<>(); + + public boolean isVerifiablePasswordAuthentication() { + return verifiablePasswordAuthentication; } - public List getApi() { - return Collections.unmodifiableList(api); + public List getHooks() { + return Collections.unmodifiableList(hooks); } public List getGit() { return Collections.unmodifiableList(git); } - public List getHooks() { - return Collections.unmodifiableList(hooks); + public List getWeb() { + return Collections.unmodifiableList(web); } - public List getImporter() { - return Collections.unmodifiableList(importer); + public List getApi() { + return Collections.unmodifiableList(api); } public List getPages() { return Collections.unmodifiableList(pages); } - public List getWeb() { - return Collections.unmodifiableList(web); - } - - public boolean isVerifiablePasswordAuthentication() { - return verifiablePasswordAuthentication; + public List getImporter() { + return Collections.unmodifiableList(importer); } } /** - * This version uses public getters and shows that package or private setters both can be used by jackson. You can - * check this by running in debug and setting break points in the setters. - * + * This version uses only public getters and returns unmodifiable lists and has final fields *

* Pro: *

    - *
  • Easy to create
  • - *
  • Not much code
  • - *
  • Some annotations
  • + *
  • Moderate amount of code
  • + *
  • More annotations
  • + *
  • Fields final and lists unmodifiable
  • *
* Con: *
    - *
  • Exposes some package setters for fields that should not be changed, better than public
  • - *
  • Lists modifiable when they should not be changed
  • + *
  • Extra allocations - default array lists will be replaced by Jackson (yes, even though they are final)
  • + *
  • Added constructor is annoying
  • + *
  • If this object could be refreshed or populated, then the final is misleading (and possibly buggy)
  • *
* * @author Liam Newman * @see org.kohsuke.github.GHMeta */ - public static class GHMetaPackage implements GHMetaExample { - - private List api; - - private List git; - private List hooks; - /** - * Missing {@link JsonProperty} or having it on the field will cause Jackson to ignore getters and setters. - */ - @JsonProperty - private List importer; - private List pages; - private boolean verifiablePasswordAuthentication; - private List web; - - /** - * Create default GHMetaPackage instance - */ - public GHMetaPackage() { - } - - @JsonProperty - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getApi() { - return api; - } - - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getGit() { - return git; - } - - @JsonProperty - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getHooks() { - return hooks; - } - - /** - * Missing {@link JsonProperty} or having it on the field will cause Jackson to ignore getters and setters. - * - * @return list of importer addresses - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getImporter() { - return importer; - } + public static class GHMetaGettersFinal implements GHMetaExample { - @JsonProperty - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getPages() { - return pages; - } + private final boolean verifiablePasswordAuthentication; + private final List hooks = new ArrayList<>(); + private final List git = new ArrayList<>(); + private final List web = new ArrayList<>(); + private final List api = new ArrayList<>(); + private final List pages = new ArrayList<>(); + private final List importer = new ArrayList<>(); - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getWeb() { - return web; + @JsonCreator + private GHMetaGettersFinal( + @JsonProperty("verifiable_password_authentication") boolean verifiablePasswordAuthentication) { + // boolean fields when final seem to be really final, so we have to switch to constructor + this.verifiablePasswordAuthentication = verifiablePasswordAuthentication; } - @JsonProperty("verifiable_password_authentication") public boolean isVerifiablePasswordAuthentication() { return verifiablePasswordAuthentication; } - /** - * Setters can be private (or package local) and will still be called by Jackson. The {@link JsonProperty} can - * got on the getter or setter and still work. - * - * @param hooks - * list of hooks - */ - private void setHooks(List hooks) { - this.hooks = hooks; - } - - private void setVerifiablePasswordAuthentication(boolean verifiablePasswordAuthentication) { - this.verifiablePasswordAuthentication = verifiablePasswordAuthentication; + public List getHooks() { + return Collections.unmodifiableList(hooks); } - void setApi(List api) { - this.api = api; + public List getGit() { + return Collections.unmodifiableList(git); } - /** - * Since we mostly use Jackson for deserialization, {@link JsonSetter} is also okay, but {@link JsonProperty} is - * preferred. - * - * @param git - * list of git addresses - */ - @JsonSetter - void setGit(List git) { - this.git = git; + public List getWeb() { + return Collections.unmodifiableList(web); } - /** - * Missing {@link JsonProperty} or having it on the field will cause Jackson to ignore getters and setters. - * - * @param importer - * list of importer addresses - */ - void setImporter(List importer) { - this.importer = importer; + public List getApi() { + return Collections.unmodifiableList(api); } - void setPages(List pages) { - this.pages = pages; + public List getPages() { + return Collections.unmodifiableList(pages); } - /** - * The {@link JsonProperty} can got on the getter or setter and still work. - * - * @param web - * list of web addresses - */ - void setWeb(List web) { - this.web = web; + public List getImporter() { + return Collections.unmodifiableList(importer); } - } /** - * This version uses public getters and setters and leaves it up to Jackson how it wants to fill them. + * This version uses only public getters and returns unmodifiable lists *

* Pro: *

    - *
  • Easy to create
  • - *
  • Not much code
  • - *
  • Minimal annotations
  • + *
  • Fields final and lists unmodifiable
  • + *
  • Construction behavior can be controlled - if values depended on each other or needed to be set in a specific + * order, this could do that.
  • + *
  • JsonProrperty "required" works on JsonCreator constructors - lets annotation define required values
  • *
* Con: *
    - *
  • Exposes public setters for fields that should not be changed, flagged by spotbugs
  • - *
  • Lists modifiable when they should not be changed
  • - *
  • Jackson generally doesn't call the setters, it just sets the fields directly
  • + *
  • There is no way you'd know about this without some research
  • + *
  • Specific annotations needed
  • + *
  • Nonnull annotations are misleading - null value is not checked even for "required" constructor + * parameters
  • + *
  • Brittle and verbose - not friendly to large number of fields
  • *
* - * @author Paulo Miguel Almeida + * @author Liam Newman * @see org.kohsuke.github.GHMeta */ - public static class GHMetaPublic implements GHMetaExample { + public static class GHMetaGettersFinalCreator implements GHMetaExample { - private List api; + private final boolean verifiablePasswordAuthentication; + private final List hooks; + private final List git; + private final List web; + private final List api; + private final List pages; + private final List importer; - private List git; - private List hooks; - private List importer; - private List pages; - @JsonProperty("verifiable_password_authentication") - private boolean verifiablePasswordAuthentication; - private List web; /** - * Create default GHMetaPublic instance + * + * @param hooks + * the hooks - required property works, but only on creator json properties like this, ignores + * Nonnull, checked manually + * @param git + * the git list - required property works, but only on creator json properties like this, misleading + * Nonnull annotation + * @param web + * the web list - misleading Nonnull annotation + * @param api + * the api list - misleading Nonnull annotation + * @param pages + * the pages list - misleading Nonnull annotation + * @param importer + * the importer list - misleading Nonnull annotation + * @param verifiablePasswordAuthentication + * true or false */ - public GHMetaPublic() { - } + @JsonCreator + private GHMetaGettersFinalCreator(@Nonnull @JsonProperty(value = "hooks", required = true) List hooks, + @Nonnull @JsonProperty(value = "git", required = true) List git, + @Nonnull @JsonProperty("web") List web, + @Nonnull @JsonProperty("api") List api, + @Nonnull @JsonProperty("pages") List pages, + @Nonnull @JsonProperty("importer") List importer, + @JsonProperty("verifiable_password_authentication") boolean verifiablePasswordAuthentication) { - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getApi() { - return api; + // to ensure a value is actually not null we still have to do a null check + Objects.requireNonNull(hooks); + + this.verifiablePasswordAuthentication = verifiablePasswordAuthentication; + this.hooks = Collections.unmodifiableList(hooks); + this.git = Collections.unmodifiableList(git); + this.web = Collections.unmodifiableList(web); + this.api = Collections.unmodifiableList(api); + this.pages = Collections.unmodifiableList(pages); + this.importer = Collections.unmodifiableList(importer); } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getGit() { - return git; + public boolean isVerifiablePasswordAuthentication() { + return verifiablePasswordAuthentication; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") public List getHooks() { return hooks; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getImporter() { - return importer; - } - - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") - public List getPages() { - return pages; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") + public List getGit() { + return git; } - @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Noted above") + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") public List getWeb() { return web; } - public boolean isVerifiablePasswordAuthentication() { - return verifiablePasswordAuthentication; - } - - /** - * Sets api. - * - * @param api - * the api - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") - public void setApi(List api) { - this.api = api; - } - - /** - * Sets git. - * - * @param git - * the git - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") - public void setGit(List git) { - this.git = git; - } - - /** - * Sets hooks. - * - * @param hooks - * the hooks - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") - public void setHooks(List hooks) { - this.hooks = hooks; - } - - /** - * Sets importer. - * - * @param importer - * the importer - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") - public void setImporter(List importer) { - this.importer = importer; - } - - /** - * Sets pages. - * - * @param pages - * the pages - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") - public void setPages(List pages) { - this.pages = pages; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") + public List getApi() { + return api; } - /** - * Sets verifiable password authentication. - * - * @param verifiablePasswordAuthentication - * the verifiable password authentication - */ - public void setVerifiablePasswordAuthentication(boolean verifiablePasswordAuthentication) { - this.verifiablePasswordAuthentication = verifiablePasswordAuthentication; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") + public List getPages() { + return pages; } - /** - * Sets web. - * - * @param web - * the web - */ - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") - public void setWeb(List web) { - this.web = web; + @SuppressFBWarnings(value = { "EI_EXPOSE_REP" }, justification = "Unmodifiable but spotbugs doesn't detect") + public List getImporter() { + return importer; } - - } - - /** - * Placeholder constructor. - */ - public ReadOnlyObjects() { } } diff --git a/src/main/java/org/kohsuke/github/extras/HttpClientGitHubConnector.java b/src/main/java/org/kohsuke/github/extras/HttpClientGitHubConnector.java index 56c05aae93..52f7e610d7 100644 --- a/src/main/java/org/kohsuke/github/extras/HttpClientGitHubConnector.java +++ b/src/main/java/org/kohsuke/github/extras/HttpClientGitHubConnector.java @@ -27,34 +27,6 @@ @SuppressFBWarnings(value = { "CT_CONSTRUCTOR_THROW" }, justification = "Basic validation") public class HttpClientGitHubConnector implements GitHubConnector { - /** - * Initial response information when a response is initially received and before the body is processed. - * - * Implementation specific to {@link HttpResponse}. - */ - private static class HttpClientGitHubConnectorResponse extends GitHubConnectorResponse { - - @Nonnull - private final HttpResponse response; - - protected HttpClientGitHubConnectorResponse(@Nonnull GitHubConnectorRequest request, - @Nonnull HttpResponse response) { - super(request, response.statusCode(), response.headers().map()); - this.response = response; - } - - @Override - public void close() throws IOException { - super.close(); - } - - @CheckForNull - @Override - protected InputStream rawBodyStream() throws IOException { - return response.body(); - } - } - private final HttpClient client; /** @@ -115,4 +87,33 @@ public GitHubConnectorResponse send(GitHubConnectorRequest connectorRequest) thr throw (InterruptedIOException) new InterruptedIOException(e.getMessage()).initCause(e); } } + + /** + * Initial response information when a response is initially received and before the body is processed. + * + * Implementation specific to {@link HttpResponse}. + */ + private static class HttpClientGitHubConnectorResponse extends GitHubConnectorResponse.ByteArrayResponse { + + @Nonnull + private final HttpResponse response; + + protected HttpClientGitHubConnectorResponse(@Nonnull GitHubConnectorRequest request, + @Nonnull HttpResponse response) { + super(request, response.statusCode(), response.headers().map()); + this.response = response; + } + + @CheckForNull + @Override + protected InputStream rawBodyStream() throws IOException { + return response.body(); + } + + @Override + public void close() throws IOException { + super.close(); + IOUtils.closeQuietly(response.body()); + } + } } diff --git a/src/main/java/org/kohsuke/github/extras/authorization/JWTTokenProvider.java b/src/main/java/org/kohsuke/github/extras/authorization/JWTTokenProvider.java index ba7d38b325..eae8a8abca 100644 --- a/src/main/java/org/kohsuke/github/extras/authorization/JWTTokenProvider.java +++ b/src/main/java/org/kohsuke/github/extras/authorization/JWTTokenProvider.java @@ -27,50 +27,18 @@ @SuppressFBWarnings(value = { "CT_CONSTRUCTOR_THROW" }, justification = "TODO") public class JWTTokenProvider implements AuthorizationProvider { - /** - * Convert a PKCS#8 formatted private key in string format into a java PrivateKey - * - * @param key - * PCKS#8 string - * @return private key - * @throws GeneralSecurityException - * if we couldn't parse the string - */ - private static PrivateKey getPrivateKeyFromString(final String key) throws GeneralSecurityException { - if (key.contains(" RSA ")) { - throw new InvalidKeySpecException( - "Private key must be a PKCS#8 formatted string, to convert it from PKCS#1 use: " - + "openssl pkcs8 -topk8 -inform PEM -outform PEM -in current-key.pem -out new-key.pem -nocrypt"); - } - - // Remove all comments and whitespace from PEM - // such as "-----BEGIN PRIVATE KEY-----" and newlines - String privateKeyContent = key.replaceAll("(?m)^--.*", "").replaceAll("\\s", ""); - - KeyFactory kf = KeyFactory.getInstance("RSA"); + private final PrivateKey privateKey; - try { - byte[] decode = Base64.getDecoder().decode(privateKeyContent); - PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(decode); + @Nonnull + private Instant validUntil = Instant.MIN; - return kf.generatePrivate(keySpecPKCS8); - } catch (IllegalArgumentException e) { - throw new InvalidKeySpecException("Failed to decode private key: " + e.getMessage(), e); - } - } + private String authorization; /** * The identifier for the application */ private final String applicationId; - private String authorization; - - private final PrivateKey privateKey; - - @Nonnull - private Instant validUntil = Instant.MIN; - /** * Create a JWTTokenProvider * @@ -108,12 +76,13 @@ public JWTTokenProvider(String applicationId, Path keyPath) throws GeneralSecuri * * @param applicationId * the application id - * @param privateKey - * the private key + * @param keyString + * the key string + * @throws GeneralSecurityException + * when an error occurs */ - public JWTTokenProvider(String applicationId, PrivateKey privateKey) { - this.privateKey = privateKey; - this.applicationId = applicationId; + public JWTTokenProvider(String applicationId, String keyString) throws GeneralSecurityException { + this(applicationId, getPrivateKeyFromString(keyString)); } /** @@ -121,13 +90,12 @@ public JWTTokenProvider(String applicationId, PrivateKey privateKey) { * * @param applicationId * the application id - * @param keyString - * the key string - * @throws GeneralSecurityException - * when an error occurs + * @param privateKey + * the private key */ - public JWTTokenProvider(String applicationId, String keyString) throws GeneralSecurityException { - this(applicationId, getPrivateKeyFromString(keyString)); + public JWTTokenProvider(String applicationId, PrivateKey privateKey) { + this.privateKey = privateKey; + this.applicationId = applicationId; } /** {@inheritDoc} */ @@ -142,6 +110,54 @@ public String getEncodedAuthorization() throws IOException { } } + /** + * Indicates whether the token considered valid. + * + *

+ * This is not the same as whether the token is expired. The token is considered not valid before it actually + * expires to prevent access denied errors. + * + *

+ * Made internal for testing + * + * @return false if the token has been refreshed within the required window, otherwise true + */ + boolean isNotValid() { + return Instant.now().isAfter(validUntil); + } + + /** + * Convert a PKCS#8 formatted private key in string format into a java PrivateKey + * + * @param key + * PCKS#8 string + * @return private key + * @throws GeneralSecurityException + * if we couldn't parse the string + */ + private static PrivateKey getPrivateKeyFromString(final String key) throws GeneralSecurityException { + if (key.contains(" RSA ")) { + throw new InvalidKeySpecException( + "Private key must be a PKCS#8 formatted string, to convert it from PKCS#1 use: " + + "openssl pkcs8 -topk8 -inform PEM -outform PEM -in current-key.pem -out new-key.pem -nocrypt"); + } + + // Remove all comments and whitespace from PEM + // such as "-----BEGIN PRIVATE KEY-----" and newlines + String privateKeyContent = key.replaceAll("(?m)^--.*", "").replaceAll("\\s", ""); + + KeyFactory kf = KeyFactory.getInstance("RSA"); + + try { + byte[] decode = Base64.getDecoder().decode(privateKeyContent); + PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(decode); + + return kf.generatePrivate(keySpecPKCS8); + } catch (IllegalArgumentException e) { + throw new InvalidKeySpecException("Failed to decode private key: " + e.getMessage(), e); + } + } + private String refreshJWT() { Instant now = Instant.now(); @@ -161,20 +177,4 @@ private String refreshJWT() { Instant getIssuedAt(Instant now) { return now.minus(Duration.ofMinutes(2)); } - - /** - * Indicates whether the token considered valid. - * - *

- * This is not the same as whether the token is expired. The token is considered not valid before it actually - * expires to prevent access denied errors. - * - *

- * Made internal for testing - * - * @return false if the token has been refreshed within the required window, otherwise true - */ - boolean isNotValid() { - return Instant.now().isAfter(validUntil); - } } diff --git a/src/main/java/org/kohsuke/github/extras/authorization/JwtBuilderUtil.java b/src/main/java/org/kohsuke/github/extras/authorization/JwtBuilderUtil.java index a5535b4973..81aa4b1272 100644 --- a/src/main/java/org/kohsuke/github/extras/authorization/JwtBuilderUtil.java +++ b/src/main/java/org/kohsuke/github/extras/authorization/JwtBuilderUtil.java @@ -25,6 +25,77 @@ */ final class JwtBuilderUtil { + private static final Logger LOGGER = Logger.getLogger(JwtBuilderUtil.class.getName()); + + private static IJwtBuilder builder; + + /** + * Build a JWT. + * + * @param issuedAt + * issued at + * @param expiration + * expiration + * @param applicationId + * application id + * @param privateKey + * private key + * @return JWT + */ + static String buildJwt(Instant issuedAt, Instant expiration, String applicationId, PrivateKey privateKey) { + if (builder == null) { + createBuilderImpl(issuedAt, expiration, applicationId, privateKey); + } + return builder.buildJwt(issuedAt, expiration, applicationId, privateKey); + } + + private static void createBuilderImpl(Instant issuedAt, + Instant expiration, + String applicationId, + PrivateKey privateKey) { + // Figure out which builder to use and cache it. We don't worry about thread safety here because we're fine if + // the builder is assigned multiple times. The end result will be the same. + try { + builder = new DefaultBuilderImpl(); + } catch (NoSuchMethodError | NoClassDefFoundError e) { + LOGGER.warning( + "You are using an outdated version of the io.jsonwebtoken:jjwt-* suite. v0.12.x or later is recommended."); + + try { + ReflectionBuilderImpl reflectionBuider = new ReflectionBuilderImpl(); + // Build a JWT to eagerly check for any reflection errors. + reflectionBuider.buildJwtWithReflection(issuedAt, expiration, applicationId, privateKey); + + builder = reflectionBuider; + } catch (ReflectiveOperationException re) { + throw new GHException( + "Could not build JWT using reflection on io.jsonwebtoken:jjwt-* suite." + + "The minimum supported version is v0.11.x, v0.12.x or later is recommended.", + re); + } + } + } + + /** + * IJwtBuilder interface to isolate loading of JWT classes allowing us to catch and handle linkage errors. + */ + interface IJwtBuilder { + /** + * Build a JWT. + * + * @param issuedAt + * issued at + * @param expiration + * expiration + * @param applicationId + * application id + * @param privateKey + * private key + * @return JWT + */ + String buildJwt(Instant issuedAt, Instant expiration, String applicationId, PrivateKey privateKey); + } + /** * A class to isolate loading of JWT classes allowing us to catch and handle linkage errors. * @@ -52,8 +123,6 @@ public String buildJwt(Instant issuedAt, Instant expiration, String applicationI SignatureAlgorithm rs256 = Jwts.SIG.RS256; JwtBuilder jwtBuilder = Jwts.builder(); - // jjwt uses the legacy java date-time api - // see https://github.com/jwtk/jjwt/issues/235 for future support for java 8 date-time api jwtBuilder = jwtBuilder.issuedAt(Date.from(issuedAt)) .expiration(Date.from(expiration)) .issuer(applicationId) @@ -68,28 +137,19 @@ public String buildJwt(Instant issuedAt, Instant expiration, String applicationI */ private static final class ReflectionBuilderImpl implements IJwtBuilder { - @SuppressWarnings("unchecked") - private static > T createEnumInstance(Class type, String name) { - return Enum.valueOf((Class) type, name); - } - private Enum rs256SignatureAlgorithm; - private Method serializeToJsonMethod; - private Method setExpirationMethod; private Method setIssuedAtMethod; + private Method setExpirationMethod; private Method setIssuerMethod; - + private Enum rs256SignatureAlgorithm; private Method signWithMethod; + private Method serializeToJsonMethod; ReflectionBuilderImpl() throws ReflectiveOperationException { JwtBuilder jwtBuilder = Jwts.builder(); Class jwtReflectionClass = jwtBuilder.getClass(); - // jjwt uses the legacy java date-time api - // see https://github.com/jwtk/jjwt/issues/235 for future support for java 8 date-time api - // noinspection UseOfObsoleteDateTimeApi setIssuedAtMethod = jwtReflectionClass.getMethod("setIssuedAt", Date.class); setIssuerMethod = jwtReflectionClass.getMethod("setIssuer", String.class); - // noinspection UseOfObsoleteDateTimeApi setExpirationMethod = jwtReflectionClass.getMethod("setExpiration", Date.class); Class signatureAlgorithmClass = Class.forName("io.jsonwebtoken.SignatureAlgorithm"); rs256SignatureAlgorithm = createEnumInstance(signatureAlgorithmClass, "RS256"); @@ -126,8 +186,6 @@ private String buildJwtWithReflection(Instant issuedAt, PrivateKey privateKey) throws IllegalAccessException, InvocationTargetException { JwtBuilder jwtBuilder = Jwts.builder(); Object builderObj = jwtBuilder; - // jjwt uses the legacy java date-time api - // see https://github.com/jwtk/jjwt/issues/235 for future support for java 8 date-time api builderObj = setIssuedAtMethod.invoke(builderObj, Date.from(issuedAt)); builderObj = setExpirationMethod.invoke(builderObj, Date.from(expiration)); builderObj = setIssuerMethod.invoke(builderObj, applicationId); @@ -135,76 +193,10 @@ private String buildJwtWithReflection(Instant issuedAt, builderObj = serializeToJsonMethod.invoke(builderObj, new JacksonSerializer<>()); return ((JwtBuilder) builderObj).compact(); } - } - /** - * IJwtBuilder interface to isolate loading of JWT classes allowing us to catch and handle linkage errors. - */ - interface IJwtBuilder { - /** - * Build a JWT. - * - * @param issuedAt - * issued at - * @param expiration - * expiration - * @param applicationId - * application id - * @param privateKey - * private key - * @return JWT - */ - String buildJwt(Instant issuedAt, Instant expiration, String applicationId, PrivateKey privateKey); - } - - private static final Logger LOGGER = Logger.getLogger(JwtBuilderUtil.class.getName()); - - private static IJwtBuilder builder; - - private static void createBuilderImpl(Instant issuedAt, - Instant expiration, - String applicationId, - PrivateKey privateKey) { - // Figure out which builder to use and cache it. We don't worry about thread safety here because we're fine if - // the builder is assigned multiple times. The end result will be the same. - try { - builder = new DefaultBuilderImpl(); - } catch (NoSuchMethodError | NoClassDefFoundError e) { - LOGGER.warning( - "You are using an outdated version of the io.jsonwebtoken:jjwt-* suite. v0.12.x or later is recommended."); - - try { - ReflectionBuilderImpl reflectionBuider = new ReflectionBuilderImpl(); - // Build a JWT to eagerly check for any reflection errors. - reflectionBuider.buildJwtWithReflection(issuedAt, expiration, applicationId, privateKey); - - builder = reflectionBuider; - } catch (ReflectiveOperationException re) { - throw new GHException( - "Could not build JWT using reflection on io.jsonwebtoken:jjwt-* suite." - + "The minimum supported version is v0.11.x, v0.12.x or later is recommended.", - re); - } - } - } - - /** - * Build a JWT. - * - * @param issuedAt - * issued at - * @param expiration - * expiration - * @param applicationId - * application id - * @param privateKey - * private key - * @return JWT - */ - static String buildJwt(Instant issuedAt, Instant expiration, String applicationId, PrivateKey privateKey) { - if (builder == null) { - createBuilderImpl(issuedAt, expiration, applicationId, privateKey); + @SuppressWarnings("unchecked") + private static > T createEnumInstance(Class type, String name) { + return Enum.valueOf((Class) type, name); } - return builder.buildJwt(issuedAt, expiration, applicationId, privateKey); } } diff --git a/src/main/java/org/kohsuke/github/extras/okhttp3/OkHttpGitHubConnector.java b/src/main/java/org/kohsuke/github/extras/okhttp3/OkHttpGitHubConnector.java index 304db22b33..d61fde220b 100644 --- a/src/main/java/org/kohsuke/github/extras/okhttp3/OkHttpGitHubConnector.java +++ b/src/main/java/org/kohsuke/github/extras/okhttp3/OkHttpGitHubConnector.java @@ -2,6 +2,7 @@ import okhttp3.*; import org.apache.commons.io.IOUtils; +import org.kohsuke.github.*; import org.kohsuke.github.connector.GitHubConnector; import org.kohsuke.github.connector.GitHubConnectorRequest; import org.kohsuke.github.connector.GitHubConnectorResponse; @@ -26,44 +27,11 @@ * @author Liam Newman */ public class OkHttpGitHubConnector implements GitHubConnector { - /** - * Initial response information when a response is initially received and before the body is processed. - * - * Implementation specific to {@link okhttp3.Response}. - */ - private static class OkHttpGitHubConnectorResponse extends GitHubConnectorResponse { - - @Nonnull - private final Response response; - - OkHttpGitHubConnectorResponse(@Nonnull GitHubConnectorRequest request, @Nonnull Response response) { - super(request, response.code(), response.headers().toMultimap()); - this.response = response; - } - - @Override - public void close() throws IOException { - super.close(); - response.close(); - } - - @CheckForNull - @Override - protected InputStream rawBodyStream() throws IOException { - ResponseBody body = response.body(); - if (body != null) { - return body.byteStream(); - } else { - return null; - } - } - } private static final String HEADER_NAME = "Cache-Control"; + private final String maxAgeHeaderValue; private final OkHttpClient client; - private final String maxAgeHeaderValue; - /** * Instantiates a new Ok http connector. * @@ -130,4 +98,37 @@ public GitHubConnectorResponse send(GitHubConnectorRequest request) throws IOExc private List TlsConnectionSpecs() { return Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT); } + + /** + * Initial response information when a response is initially received and before the body is processed. + * + * Implementation specific to {@link okhttp3.Response}. + */ + private static class OkHttpGitHubConnectorResponse extends GitHubConnectorResponse.ByteArrayResponse { + + @Nonnull + private final Response response; + + OkHttpGitHubConnectorResponse(@Nonnull GitHubConnectorRequest request, @Nonnull Response response) { + super(request, response.code(), response.headers().toMultimap()); + this.response = response; + } + + @CheckForNull + @Override + protected InputStream rawBodyStream() throws IOException { + ResponseBody body = response.body(); + if (body != null) { + return body.byteStream(); + } else { + return null; + } + } + + @Override + public void close() throws IOException { + super.close(); + response.close(); + } + } } diff --git a/src/main/java/org/kohsuke/github/internal/DefaultGitHubConnector.java b/src/main/java/org/kohsuke/github/internal/DefaultGitHubConnector.java index 5cf79548ad..d7cb0b7522 100644 --- a/src/main/java/org/kohsuke/github/internal/DefaultGitHubConnector.java +++ b/src/main/java/org/kohsuke/github/internal/DefaultGitHubConnector.java @@ -14,6 +14,9 @@ */ public final class DefaultGitHubConnector { + private DefaultGitHubConnector() { + } + /** * Creates a {@link GitHubConnector} that will be used as the default connector. * @@ -44,7 +47,4 @@ static GitHubConnector create(String defaultConnectorProperty) { "Property 'test.github.connector' must reference a valid built-in connector - okhttp, httpclient, or default."); } } - - private DefaultGitHubConnector() { - } } diff --git a/src/main/java/org/kohsuke/github/internal/EnumUtils.java b/src/main/java/org/kohsuke/github/internal/EnumUtils.java index 94f867333a..9c4253b3cc 100644 --- a/src/main/java/org/kohsuke/github/internal/EnumUtils.java +++ b/src/main/java/org/kohsuke/github/internal/EnumUtils.java @@ -11,8 +11,10 @@ public final class EnumUtils { private static final Logger LOGGER = Logger.getLogger(EnumUtils.class.getName()); /** - * Returns an enum value matching the value if found, {@code defaultEnum} if the value is null or cannot be matched - * to a value of the enum. + * Returns an enum value matching the value if found, null if the value is null and {@code defaultEnum} if the value + * cannot be matched to a value of the enum. + *

+ * The value is converted to uppercase before being matched to the enum values. * * @param * the type of the enum @@ -22,26 +24,18 @@ public final class EnumUtils { * the value to interpret * @param defaultEnum * the default enum value if the value doesn't match one of the enum value - * @return an enum value + * @return an enum value or null */ - public static > E getEnumOrDefault(Class enumClass, String value, E defaultEnum) { - try { - if (value != null) { - return Enum.valueOf(enumClass, value.toUpperCase(Locale.ROOT)); - } - } catch (IllegalArgumentException e) { + public static > E getNullableEnumOrDefault(Class enumClass, String value, E defaultEnum) { + if (value == null) { + return null; } - - LOGGER.warning("Unknown value " + value + " for enum class " + enumClass.getName() + ", defaulting to " - + defaultEnum.name()); - return defaultEnum; + return getEnumOrDefault(enumClass, value, defaultEnum); } /** - * Returns an enum value matching the value if found, null if the value is null and {@code defaultEnum} if the value - * cannot be matched to a value of the enum. - *

- * The value is converted to uppercase before being matched to the enum values. + * Returns an enum value matching the value if found, {@code defaultEnum} if the value is null or cannot be matched + * to a value of the enum. * * @param * the type of the enum @@ -51,13 +45,19 @@ public static > E getEnumOrDefault(Class enumClass, String * the value to interpret * @param defaultEnum * the default enum value if the value doesn't match one of the enum value - * @return an enum value or null + * @return an enum value */ - public static > E getNullableEnumOrDefault(Class enumClass, String value, E defaultEnum) { - if (value == null) { - return null; + public static > E getEnumOrDefault(Class enumClass, String value, E defaultEnum) { + try { + if (value != null) { + return Enum.valueOf(enumClass, value.toUpperCase(Locale.ROOT)); + } + } catch (IllegalArgumentException e) { } - return getEnumOrDefault(enumClass, value, defaultEnum); + + LOGGER.warning("Unknown value " + value + " for enum class " + enumClass.getName() + ", defaulting to " + + defaultEnum.name()); + return defaultEnum; } private EnumUtils() { diff --git a/src/main/java/org/kohsuke/github/internal/graphql/response/GHGraphQLResponse.java b/src/main/java/org/kohsuke/github/internal/graphql/response/GHGraphQLResponse.java deleted file mode 100644 index 07d012caee..0000000000 --- a/src/main/java/org/kohsuke/github/internal/graphql/response/GHGraphQLResponse.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.kohsuke.github.internal.graphql.response; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -/** - * A response of GraphQL. - *

- * This class is used to parse the response of GraphQL. - *

- * - * @param - * the type of data - */ -public class GHGraphQLResponse { - - /** - * A GraphQL response with basic Object data type. - */ - public static class ObjectResponse extends GHGraphQLResponse { - /** - * ObjectResponse constructor. - * - * @param data - * GraphQL success response - * @param errors - * GraphQL failure response, This will be empty if not fail - */ - @JsonCreator - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") - public ObjectResponse(@JsonProperty("data") Object data, @JsonProperty("errors") List errors) { - super(data, errors); - } - } - - /** - * A error of GraphQL response. Minimum implementation for GraphQL error. - */ - @SuppressFBWarnings(value = { "UWF_UNWRITTEN_FIELD", "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" }, - justification = "JSON API") - private static class GraphQLError { - private String message; - - public String getMessage() { - return message; - } - } - - private final T data; - - private final List errors; - - /** - * GHGraphQLResponse constructor - * - * @param data - * GraphQL success response - * @param errors - * GraphQL failure response, This will be empty if not fail - */ - @JsonCreator - @SuppressFBWarnings(value = { "EI_EXPOSE_REP2" }, justification = "Spotbugs also doesn't like this") - public GHGraphQLResponse(@JsonProperty("data") T data, @JsonProperty("errors") List errors) { - if (errors == null) { - errors = Collections.emptyList(); - } - this.data = data; - this.errors = Collections.unmodifiableList(errors); - } - - /** - * Get response data. - * - * @return GraphQL success response - */ - public T getData() { - if (!isSuccessful()) { - throw new RuntimeException("Response not successful, data invalid"); - } - - return data; - } - - /** - * Get response error message. - * - * @return GraphQL error messages from Github Response. Empty list when no errors occurred. - */ - public List getErrorMessages() { - return errors.stream().map(GraphQLError::getMessage).collect(Collectors.toList()); - } - - /** - * Is response succesful. - * - * @return request is succeeded. True when error list is empty. - */ - public boolean isSuccessful() { - return errors.isEmpty(); - } -} diff --git a/src/main/resources/META-INF/native-image/org.kohsuke/github-api/reflect-config.json b/src/main/resources/META-INF/native-image/org.kohsuke/github-api/reflect-config.json index 30be262b74..fbb6b3cc5a 100644 --- a/src/main/resources/META-INF/native-image/org.kohsuke/github-api/reflect-config.json +++ b/src/main/resources/META-INF/native-image/org.kohsuke/github-api/reflect-config.json @@ -6705,112 +6705,7 @@ "allDeclaredClasses": true }, { - "name": "org.kohsuke.github.GHPullRequest$EnablePullRequestAutoMergeResponse", - "allPublicFields": true, - "allDeclaredFields": true, - "queryAllPublicConstructors": true, - "queryAllDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredConstructors": true, - "queryAllPublicMethods": true, - "queryAllDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredMethods": true, - "allPublicClasses": true, - "allDeclaredClasses": true - }, - { - "name": "org.kohsuke.github.GHPullRequest$EnablePullRequestAutoMergeResponse$EnablePullRequestAutoMerge", - "allPublicFields": true, - "allDeclaredFields": true, - "queryAllPublicConstructors": true, - "queryAllDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredConstructors": true, - "queryAllPublicMethods": true, - "queryAllDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredMethods": true, - "allPublicClasses": true, - "allDeclaredClasses": true - }, - { - "name": "org.kohsuke.github.GHPullRequest$EnablePullRequestAutoMergeResponse$EnablePullRequestAutoMerge$EnablePullRequestAutoMergePullRequest", - "allPublicFields": true, - "allDeclaredFields": true, - "queryAllPublicConstructors": true, - "queryAllDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredConstructors": true, - "queryAllPublicMethods": true, - "queryAllDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredMethods": true, - "allPublicClasses": true, - "allDeclaredClasses": true - }, - { - "name": "org.kohsuke.github.internal.graphql.response.GHGraphQLResponse", - "allPublicFields": true, - "allDeclaredFields": true, - "queryAllPublicConstructors": true, - "queryAllDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredConstructors": true, - "queryAllPublicMethods": true, - "queryAllDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredMethods": true, - "allPublicClasses": true, - "allDeclaredClasses": true - }, - { - "name": "org.kohsuke.github.internal.graphql.response.GHGraphQLResponse$GraphQLError", - "allPublicFields": true, - "allDeclaredFields": true, - "queryAllPublicConstructors": true, - "queryAllDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredConstructors": true, - "queryAllPublicMethods": true, - "queryAllDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredMethods": true, - "allPublicClasses": true, - "allDeclaredClasses": true - }, - { - "name": "org.kohsuke.github.internal.graphql.response.GHGraphQLResponse$ObjectResponse", - "allPublicFields": true, - "allDeclaredFields": true, - "queryAllPublicConstructors": true, - "queryAllDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredConstructors": true, - "queryAllPublicMethods": true, - "queryAllDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredMethods": true, - "allPublicClasses": true, - "allDeclaredClasses": true - }, - { - "name": "org.kohsuke.github.GHAutolink", - "allPublicFields": true, - "allDeclaredFields": true, - "queryAllPublicConstructors": true, - "queryAllDeclaredConstructors": true, - "allPublicConstructors": true, - "allDeclaredConstructors": true, - "queryAllPublicMethods": true, - "queryAllDeclaredMethods": true, - "allPublicMethods": true, - "allDeclaredMethods": true, - "allPublicClasses": true, - "allDeclaredClasses": true - }, - { - "name": "org.kohsuke.github.GitHubBridgeAdapterObject", + "name": "org.kohsuke.github.GHEventPayload$Milestone", "allPublicFields": true, "allDeclaredFields": true, "queryAllPublicConstructors": true, @@ -6824,5 +6719,4 @@ "allPublicClasses": true, "allDeclaredClasses": true } - ] diff --git a/src/main/resources/META-INF/native-image/org.kohsuke/github-api/serialization-config.json b/src/main/resources/META-INF/native-image/org.kohsuke/github-api/serialization-config.json index 412aa47e18..6c7dd370a1 100644 --- a/src/main/resources/META-INF/native-image/org.kohsuke/github-api/serialization-config.json +++ b/src/main/resources/META-INF/native-image/org.kohsuke/github-api/serialization-config.json @@ -119,9 +119,6 @@ { "name": "org.kohsuke.github.GHAppInstallationsPage" }, - { - "name": "org.kohsuke.github.GHAppInstallationRequest" - }, { "name": "org.kohsuke.github.GHAppInstallationToken" }, @@ -1342,29 +1339,5 @@ }, { "name": "org.kohsuke.github.SkipFromToString" - }, - { - "name": "org.kohsuke.github.GHPullRequest$EnablePullRequestAutoMergeResponse" - }, - { - "name": "org.kohsuke.github.GHPullRequest$EnablePullRequestAutoMergeResponse$EnablePullRequestAutoMerge" - }, - { - "name": "org.kohsuke.github.GHPullRequest$EnablePullRequestAutoMergeResponse$EnablePullRequestAutoMerge$EnablePullRequestAutoMergePullRequest" - }, - { - "name": "org.kohsuke.github.internal.graphql.response.GHGraphQLResponse" - }, - { - "name": "org.kohsuke.github.internal.graphql.response.GHGraphQLResponse$GraphQLError" - }, - { - "name": "org.kohsuke.github.internal.graphql.response.GHGraphQLResponse$ObjectResponse" - }, - { - "name": "org.kohsuke.github.GHAutolink" - }, - { - "name": "org.kohsuke.github.GitHubBridgeAdapterObject" } -] +] \ No newline at end of file diff --git a/src/test/java/org/kohsuke/github/AbstractGHAppInstallationTest.java b/src/test/java/org/kohsuke/github/AbstractGHAppInstallationTest.java index 8a90c4f458..da7d7f2f96 100644 --- a/src/test/java/org/kohsuke/github/AbstractGHAppInstallationTest.java +++ b/src/test/java/org/kohsuke/github/AbstractGHAppInstallationTest.java @@ -32,12 +32,12 @@ public class AbstractGHAppInstallationTest extends AbstractGitHubWireMockTest { private static String ENV_GITHUB_APP_ORG = "GITHUB_APP_ORG"; private static String ENV_GITHUB_APP_REPO = "GITHUB_APP_REPO"; - private static String PRIVATE_KEY_FILE_APP_1 = "/ghapi-test-app-1.private-key.pem"; - private static String PRIVATE_KEY_FILE_APP_2 = "/ghapi-test-app-2.private-key.pem"; - private static String PRIVATE_KEY_FILE_APP_3 = "/ghapi-test-app-3.private-key.pem"; private static String TEST_APP_ID_1 = "82994"; private static String TEST_APP_ID_2 = "83009"; private static String TEST_APP_ID_3 = "89368"; + private static String PRIVATE_KEY_FILE_APP_1 = "/ghapi-test-app-1.private-key.pem"; + private static String PRIVATE_KEY_FILE_APP_2 = "/ghapi-test-app-2.private-key.pem"; + private static String PRIVATE_KEY_FILE_APP_3 = "/ghapi-test-app-3.private-key.pem"; /** The jwt provider 1. */ protected final AuthorizationProvider jwtProvider1; diff --git a/src/test/java/org/kohsuke/github/AbstractGitHubWireMockTest.java b/src/test/java/org/kohsuke/github/AbstractGitHubWireMockTest.java index 0b52a9d49e..7cea51bda0 100644 --- a/src/test/java/org/kohsuke/github/AbstractGitHubWireMockTest.java +++ b/src/test/java/org/kohsuke/github/AbstractGitHubWireMockTest.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; @@ -30,42 +31,7 @@ */ public abstract class AbstractGitHubWireMockTest { - /** - * The Class TemplatingHelper. - */ - protected static class TemplatingHelper { - - /** The test start date. */ - @SuppressWarnings("UseOfObsoleteDateTimeApi") - public Date testStartDate = new Date(); - - /** - * Instantiate TemplatingHelper - */ - public TemplatingHelper() { - } - - /** - * New response transformer. - * - * @return the response template transformer - */ - public ResponseTemplateTransformer newResponseTransformer() { - // noinspection UnqualifiedFieldAccess - testStartDate = new Date(); - return ResponseTemplateTransformer.builder() - .global(true) - .maxCacheEntries(0L) - .helper("testStartDate", new Helper<>() { - private HandlebarsCurrentDateHelper helper = new HandlebarsCurrentDateHelper(); - @Override - public Object apply(final Object context, final Options options) throws IOException { - return this.helper.apply(TemplatingHelper.this.testStartDate, options); - } - }) - .build(); - } - } + private final GitHubBuilder githubBuilder = createGitHubBuilder(); /** The Constant GITHUB_API_TEST_ORG. */ final static String GITHUB_API_TEST_ORG = "hub4j-test-org"; @@ -76,63 +42,46 @@ public Object apply(final Object context, final Options options) throws IOExcept /** The Constant STUBBED_USER_PASSWORD. */ final static String STUBBED_USER_PASSWORD = "placeholder-password"; - /** - * Assert that. - * - * @param - * the generic type - * @param reason - * the reason - * @param actual - * the actual - * @param matcher - * the matcher - */ - public static void assertThat(String reason, T actual, Matcher matcher) { - MatcherAssert.assertThat(reason, actual, matcher); - } + /** The use default git hub. */ + protected boolean useDefaultGitHub = true; - /** - * Assert that. - * - * @param reason - * the reason - * @param assertion - * the assertion - */ - public static void assertThat(String reason, boolean assertion) { - MatcherAssert.assertThat(reason, assertion); - } + /** The temp git hub repositories. */ + protected final Set tempGitHubRepositories = new HashSet<>(); /** - * Assert that. - * - * @param - * the generic type - * @param actual - * the actual - * @param matcher - * the matcher + * {@link GitHub} instance for use during test. Traffic will be part of snapshot when taken. */ - public static void assertThat(T actual, Matcher matcher) { - MatcherAssert.assertThat("", actual, matcher); - } + protected GitHub gitHub; + + private GitHub nonRecordingGitHub; + + /** The base files class path. */ + protected final String baseFilesClassPath = this.getClass().getName().replace('.', '/'); + + /** The base record path. */ + protected final String baseRecordPath = "src/test/resources/" + baseFilesClassPath + "/wiremock"; + + /** The mock git hub. */ + @Rule + public final GitHubWireMockRule mockGitHub; + + /** The templating. */ + protected final TemplatingHelper templating = new TemplatingHelper(); /** - * Fail. + * Instantiates a new abstract git hub wire mock test. */ - public static void fail() { - Assert.fail(); + public AbstractGitHubWireMockTest() { + mockGitHub = new GitHubWireMockRule(this.getWireMockOptions()); } /** - * Fail. + * Gets the wire mock options. * - * @param reason - * the reason + * @return the wire mock options */ - public static void fail(String reason) { - Assert.fail(reason); + protected WireMockConfiguration getWireMockOptions() { + return WireMockConfiguration.options().dynamicPort().usingFilesUnderDirectory(baseRecordPath); } private static GitHubBuilder createGitHubBuilder() { @@ -166,80 +115,21 @@ private static GitHubBuilder createGitHubBuilder() { } /** - * Gets the user. + * Gets the git hub builder. * - * @param gitHub - * the git hub - * @return the user - */ - protected static GHUser getUser(GitHub gitHub) { - try { - return gitHub.getMyself(); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - /** The mock git hub. */ - @Rule - public final GitHubWireMockRule mockGitHub; - - private final GitHubBuilder githubBuilder = createGitHubBuilder(); - - private GitHub nonRecordingGitHub; - - /** The base files class path. */ - protected final String baseFilesClassPath = this.getClass().getName().replace('.', '/'); - - /** The base record path. */ - protected final String baseRecordPath = "src/test/resources/" + baseFilesClassPath + "/wiremock"; - - /** - * {@link GitHub} instance for use during test. Traffic will be part of snapshot when taken. - */ - protected GitHub gitHub; - - /** The temp git hub repositories. */ - protected final Set tempGitHubRepositories = new HashSet<>(); - - /** The templating. */ - protected final TemplatingHelper templating = new TemplatingHelper(); - - /** The use default git hub. */ - protected boolean useDefaultGitHub = true; - - /** - * Instantiates a new abstract git hub wire mock test. + * @return the git hub builder */ - public AbstractGitHubWireMockTest() { - mockGitHub = new GitHubWireMockRule(this.getWireMockOptions()); - } + protected GitHubBuilder getGitHubBuilder() { + GitHubBuilder builder = githubBuilder.clone(); - /** - * Cleanup temp repositories. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Before - @After - public void cleanupTempRepositories() throws IOException { - if (mockGitHub.isUseProxy()) { - for (String fullName : tempGitHubRepositories) { - cleanupRepository(fullName); - } + if (!mockGitHub.isUseProxy()) { + // This sets the user and password to a placeholder for wiremock testing + // This makes the tests believe they are running with permissions + // The recorded stubs will behave like they running with permissions + builder.withOAuthToken(STUBBED_USER_PASSWORD, STUBBED_USER_LOGIN); } - } - /** - * {@link GitHub} instance for use before/after test. Traffic will not be part of snapshot when taken. Should only - * be used when isUseProxy() or isTakeSnapShot(). - * - * @return a github instance after checking Authentication - */ - public GitHub getNonRecordingGitHub() { - verifyAuthenticated(nonRecordingGitHub); - return nonRecordingGitHub; + return builder; } /** @@ -263,59 +153,60 @@ public void wireMockSetup() throws Exception { } } - private GHCreateRepositoryBuilder getCreateBuilder(String name) throws IOException { - GitHub github = getNonRecordingGitHub(); - - if (mockGitHub.isTestWithOrg()) { - return github.getOrganization(GITHUB_API_TEST_ORG).createRepository(name); - } - - return github.createRepository(name); + /** + * Snapshot not allowed. + */ + protected void snapshotNotAllowed() { + assumeFalse("Test contains hand written mappings. Only valid when not taking a snapshot.", + mockGitHub.isTakeSnapshot()); } - private String getOrganization() throws IOException { - return mockGitHub.isTestWithOrg() ? GITHUB_API_TEST_ORG : gitHub.getMyself().getLogin(); + /** + * Require proxy. + * + * @param reason + * the reason + */ + protected void requireProxy(String reason) { + assumeTrue("Test only valid when proxying (-Dtest.github.useProxy to enable): " + reason, + mockGitHub.isUseProxy()); } /** - * Cleanup repository. + * Verify authenticated. * - * @param fullName - * the full name - * @throws IOException - * Signals that an I/O exception has occurred. + * @param instance + * the instance */ - protected void cleanupRepository(String fullName) throws IOException { - if (mockGitHub.isUseProxy()) { - tempGitHubRepositories.add(fullName); - try { - GHRepository repository = getNonRecordingGitHub().getRepository(fullName); - if (repository != null) { - repository.delete(); - } - } catch (GHFileNotFoundException e) { - // Repo already deleted - } - - } + protected void verifyAuthenticated(GitHub instance) { + assertThat( + "GitHub connection believes it is anonymous. Make sure you set GITHUB_OAUTH or both GITHUB_LOGIN and GITHUB_PASSWORD environment variables", + instance.isAnonymous(), + Matchers.is(false)); } /** - * Gets the git hub builder. + * Gets the user. * - * @return the git hub builder + * @return the user */ - protected GitHubBuilder getGitHubBuilder() { - GitHubBuilder builder = githubBuilder.clone(); + protected GHUser getUser() { + return getUser(gitHub); + } - if (!mockGitHub.isUseProxy()) { - // This sets the user and password to a placeholder for wiremock testing - // This makes the tests believe they are running with permissions - // The recorded stubs will behave like they running with permissions - builder.withOAuthToken(STUBBED_USER_PASSWORD, STUBBED_USER_LOGIN); + /** + * Gets the user. + * + * @param gitHub + * the git hub + * @return the user + */ + protected static GHUser getUser(GitHub gitHub) { + try { + return gitHub.getMyself(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); } - - return builder; } /** @@ -365,21 +256,53 @@ protected GHRepository getTempRepository(String name) throws IOException { } /** - * Gets the user. + * Cleanup temp repositories. * - * @return the user + * @throws IOException + * Signals that an I/O exception has occurred. */ - protected GHUser getUser() { - return getUser(gitHub); + @Before + @After + public void cleanupTempRepositories() throws IOException { + if (mockGitHub.isUseProxy()) { + for (String fullName : tempGitHubRepositories) { + cleanupRepository(fullName); + } + } } /** - * Gets the wire mock options. + * Cleanup repository. * - * @return the wire mock options + * @param fullName + * the full name + * @throws IOException + * Signals that an I/O exception has occurred. */ - protected WireMockConfiguration getWireMockOptions() { - return WireMockConfiguration.options().dynamicPort().usingFilesUnderDirectory(baseRecordPath); + protected void cleanupRepository(String fullName) throws IOException { + if (mockGitHub.isUseProxy()) { + tempGitHubRepositories.add(fullName); + try { + GHRepository repository = getNonRecordingGitHub().getRepository(fullName); + if (repository != null) { + repository.delete(); + } + } catch (GHFileNotFoundException e) { + // Repo already deleted + } + + } + } + + /** + * {@link GitHub} instance for use before/after test. Traffic will not be part of snapshot when taken. Should only + * be used when isUseProxy() or isTakeSnapShot(). + * + * @return a github instance after checking Authentication + */ + public GitHub getNonRecordingGitHub() { + verifyAuthenticated(nonRecordingGitHub); + return nonRecordingGitHub; } /** @@ -394,36 +317,112 @@ protected void kohsuke() { // assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2")); } + private GHCreateRepositoryBuilder getCreateBuilder(String name) throws IOException { + GitHub github = getNonRecordingGitHub(); + + if (mockGitHub.isTestWithOrg()) { + return github.getOrganization(GITHUB_API_TEST_ORG).createRepository(name); + } + + return github.createRepository(name); + } + + private String getOrganization() throws IOException { + return mockGitHub.isTestWithOrg() ? GITHUB_API_TEST_ORG : gitHub.getMyself().getLogin(); + } + /** - * Require proxy. + * Fail. + */ + public static void fail() { + Assert.fail(); + } + + /** + * Fail. * * @param reason * the reason */ - protected void requireProxy(String reason) { - assumeTrue("Test only valid when proxying (-Dtest.github.useProxy to enable): " + reason, - mockGitHub.isUseProxy()); + public static void fail(String reason) { + Assert.fail(reason); } /** - * Snapshot not allowed. + * Assert that. + * + * @param + * the generic type + * @param actual + * the actual + * @param matcher + * the matcher */ - protected void snapshotNotAllowed() { - assumeFalse("Test contains hand written mappings. Only valid when not taking a snapshot.", - mockGitHub.isTakeSnapshot()); + public static void assertThat(T actual, Matcher matcher) { + MatcherAssert.assertThat("", actual, matcher); } /** - * Verify authenticated. + * Assert that. * - * @param instance - * the instance + * @param + * the generic type + * @param reason + * the reason + * @param actual + * the actual + * @param matcher + * the matcher */ - protected void verifyAuthenticated(GitHub instance) { - assertThat( - "GitHub connection believes it is anonymous. Make sure you set GITHUB_OAUTH or both GITHUB_LOGIN and GITHUB_PASSWORD environment variables", - instance.isAnonymous(), - Matchers.is(false)); + public static void assertThat(String reason, T actual, Matcher matcher) { + MatcherAssert.assertThat(reason, actual, matcher); + } + + /** + * Assert that. + * + * @param reason + * the reason + * @param assertion + * the assertion + */ + public static void assertThat(String reason, boolean assertion) { + MatcherAssert.assertThat(reason, assertion); + } + + /** + * The Class TemplatingHelper. + */ + protected static class TemplatingHelper { + + /** The test start date. */ + public Date testStartDate = new Date(); + + /** + * Instantiate TemplatingHelper + */ + public TemplatingHelper() { + } + + /** + * New response transformer. + * + * @return the response template transformer + */ + public ResponseTemplateTransformer newResponseTransformer() { + testStartDate = new Date(); + return ResponseTemplateTransformer.builder() + .global(true) + .maxCacheEntries(0L) + .helper("testStartDate", new Helper() { + private HandlebarsCurrentDateHelper helper = new HandlebarsCurrentDateHelper(); + @Override + public Object apply(final Object context, final Options options) throws IOException { + return this.helper.apply(TemplatingHelper.this.testStartDate, options); + } + }) + .build(); + } } } diff --git a/src/test/java/org/kohsuke/github/AbuseLimitHandlerTest.java b/src/test/java/org/kohsuke/github/AbuseLimitHandlerTest.java index 2a36f2a58f..2a723d14f3 100644 --- a/src/test/java/org/kohsuke/github/AbuseLimitHandlerTest.java +++ b/src/test/java/org/kohsuke/github/AbuseLimitHandlerTest.java @@ -40,23 +40,20 @@ public class AbuseLimitHandlerTest extends AbstractGitHubWireMockTest { /** - * This is making an assertion about the behaviour of the mock, so it's useful for making sure we're on the right - * mock, but should not be used to validate assumptions about the behaviour of the actual GitHub API. + * Instantiates a new abuse limit handler test. */ - private static void checkErrorMessageMatches(GitHubConnectorResponse connectorResponse, String substring) - throws IOException { - try (InputStream errorStream = connectorResponse.bodyStream()) { - assertThat(errorStream, notNullValue()); - String errorString = IOUtils.toString(errorStream, StandardCharsets.UTF_8); - assertThat(errorString, containsString(substring)); - } + public AbuseLimitHandlerTest() { + useDefaultGitHub = false; } /** - * Instantiates a new abuse limit handler test. + * Gets the wire mock options. + * + * @return the wire mock options */ - public AbuseLimitHandlerTest() { - useDefaultGitHub = false; + @Override + protected WireMockConfiguration getWireMockOptions() { + return super.getWireMockOptions().extensions(templating.newResponseTransformer()); } /** @@ -389,6 +386,19 @@ public void onError(@NotNull GitHubConnectorResponse connectorResponse) throws I assertThat(mockGitHub.getRequestCount(), equalTo(3)); } + /** + * This is making an assertion about the behaviour of the mock, so it's useful for making sure we're on the right + * mock, but should not be used to validate assumptions about the behaviour of the actual GitHub API. + */ + private static void checkErrorMessageMatches(GitHubConnectorResponse connectorResponse, String substring) + throws IOException { + try (InputStream errorStream = connectorResponse.bodyStream()) { + assertThat(errorStream, notNullValue()); + String errorString = IOUtils.toString(errorStream, StandardCharsets.UTF_8); + assertThat(errorString, containsString(substring)); + } + } + /** * Tests the behavior of the GitHub API client when the abuse limit handler is set to WAIT then the handler waits * appropriately when secondary rate limits are encountered. @@ -572,14 +582,4 @@ public void onError(@NotNull GitHubConnectorResponse connectorResponse) throws I getTempRepository(); assertThat(mockGitHub.getRequestCount(), equalTo(3)); } - - /** - * Gets the wire mock options. - * - * @return the wire mock options - */ - @Override - protected WireMockConfiguration getWireMockOptions() { - return super.getWireMockOptions().extensions(templating.newResponseTransformer()); - } } diff --git a/src/test/java/org/kohsuke/github/AotIntegrationTest.java b/src/test/java/org/kohsuke/github/AotIntegrationTest.java index a8b458f792..8605d8aa46 100644 --- a/src/test/java/org/kohsuke/github/AotIntegrationTest.java +++ b/src/test/java/org/kohsuke/github/AotIntegrationTest.java @@ -39,14 +39,12 @@ public AotIntegrationTest() { */ @Test public void testIfAllRequiredClassesAreRegisteredForAot() throws IOException { - String artifactId = System.getProperty("test.projectArtifactId", "default"); - Stream providedReflectionConfigStreamOfNames = readAotConfigToStreamOfClassNames( - "./target/classes/META-INF/native-image/org.kohsuke/" + artifactId + "/reflect-config.json"); + "./target/classes/META-INF/native-image/org.kohsuke/github-api/reflect-config.json"); Stream providedNoReflectStreamOfNames = Files .lines(Path.of("./target/test-classes/no-reflect-and-serialization-list")); Stream providedSerializationStreamOfNames = readAotConfigToStreamOfClassNames( - "./target/classes/META-INF/native-image/org.kohsuke/" + artifactId + "/serialization-config.json"); + "./target/classes/META-INF/native-image/org.kohsuke/github-api/serialization-config.json"); Stream providedAotConfigClassNamesPart = Stream .concat(providedSerializationStreamOfNames, Stream.concat(providedReflectionConfigStreamOfNames, providedNoReflectStreamOfNames)) @@ -55,11 +53,9 @@ public void testIfAllRequiredClassesAreRegisteredForAot() throws IOException { .collect(Collectors.toList()); Stream generatedReflectConfigStreamOfClassNames = readAotConfigToStreamOfClassNames( - "./target/spring-aot/test/resources/META-INF/native-image/org.kohsuke/" + artifactId - + "/reflect-config.json"); + "./target/spring-aot/test/resources/META-INF/native-image/org.kohsuke/github-api/reflect-config.json"); Stream generatedSerializationStreamOfNames = readAotConfigToStreamOfClassNames( - "./target/spring-aot/test/resources/META-INF/native-image/org.kohsuke/" + artifactId - + "/serialization-config.json"); + "./target/spring-aot/test/resources/META-INF/native-image/org.kohsuke/github-api/serialization-config.json"); Stream generatedAotConfigClassNames = Stream.concat(generatedReflectConfigStreamOfClassNames, generatedSerializationStreamOfNames); diff --git a/src/test/java/org/kohsuke/github/AotTestRuntimeHints.java b/src/test/java/org/kohsuke/github/AotTestRuntimeHints.java index bc357abb57..9f184dee66 100644 --- a/src/test/java/org/kohsuke/github/AotTestRuntimeHints.java +++ b/src/test/java/org/kohsuke/github/AotTestRuntimeHints.java @@ -20,12 +20,12 @@ */ public class AotTestRuntimeHints implements RuntimeHintsRegistrar { + private static final Logger LOGGER = Logger.getLogger(AotTestRuntimeHints.class.getName()); + private static final String CLASSPATH_IDENTIFIER = "/target/classes"; private static final String LOCATION_PATTERN_OF_ORG_KOHSUKE_GITHUB_CLASSES = "classpath*:org/kohsuke/github/**/*.class"; - private static final Logger LOGGER = Logger.getLogger(AotTestRuntimeHints.class.getName()); - /** * Default constructor. */ diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index cb59f2af62..9f73194b15 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -28,663 +28,561 @@ */ public class AppTest extends AbstractGitHubWireMockTest { - /** The Constant GITHUB_API_TEST_REPO. */ - static final String GITHUB_API_TEST_REPO = "github-api-test"; - /** * Create default AppTest instance */ public AppTest() { } + /** The Constant GITHUB_API_TEST_REPO. */ + static final String GITHUB_API_TEST_REPO = "github-api-test"; + /** - * Blob. + * Test repo CRUD. * * @throws Exception * the exception */ @Test - public void blob() throws Exception { - Assume.assumeFalse(SystemUtils.IS_OS_WINDOWS); + public void testRepoCRUD() throws Exception { + String targetName = "github-api-test-rename2"; - GHRepository r = gitHub.getRepository("hub4j/github-api"); - String sha1 = "a12243f2fc5b8c2ba47dd677d0b0c7583539584d"; + cleanupUserRepository("github-api-test-rename"); + cleanupUserRepository(targetName); - verifyBlobContent(r.readBlob(sha1)); + GHRepository r = gitHub.createRepository("github-api-test-rename") + .description("a test repository") + .homepage("http://github-api.kohsuke.org/") + .private_(false) + .create(); - GHBlob blob = r.getBlob(sha1); - verifyBlobContent(blob.read()); - assertThat(blob.getSha(), is("a12243f2fc5b8c2ba47dd677d0b0c7583539584d")); - assertThat(blob.getSize(), is(1104L)); + assertThat(r.hasIssues(), is(true)); + assertThat(r.hasWiki(), is(true)); + assertThat(r.hasDownloads(), is(true)); + assertThat(r.hasProjects(), is(true)); + + r.enableIssueTracker(false); + r.enableDownloads(false); + r.enableWiki(false); + r.enableProjects(false); + + r.renameTo(targetName); + + // local instance remains unchanged + assertThat(r.getName(), equalTo("github-api-test-rename")); + assertThat(r.hasIssues(), is(true)); + assertThat(r.hasWiki(), is(true)); + assertThat(r.hasDownloads(), is(true)); + assertThat(r.hasProjects(), is(true)); + + r = gitHub.getMyself().getRepository(targetName); + + // values are updated + assertThat(r.hasIssues(), is(false)); + assertThat(r.hasWiki(), is(false)); + assertThat(r.hasDownloads(), is(false)); + assertThat(r.getName(), equalTo(targetName)); + + assertThat(r.hasProjects(), is(false)); + + r.delete(); } /** - * Check to string. + * Test repository with auto initialization CRUD. * * @throws Exception * the exception */ - @Ignore("Needs mocking check") @Test - public void checkToString() throws Exception { - // Just basic code coverage to make sure toString() doesn't blow up - GHUser u = gitHub.getUser("rails"); - // System.out.println(u); - GHRepository r = u.getRepository("rails"); - // System.out.println(r); - // System.out.println(r.getIssue(1)); + public void testRepositoryWithAutoInitializationCRUD() throws Exception { + String name = "github-api-test-autoinit"; + cleanupUserRepository(name); + GHRepository r = gitHub.createRepository(name) + .description("a test repository for auto init") + .homepage("http://github-api.kohsuke.org/") + .autoInit(true) + .create(); + if (mockGitHub.isUseProxy()) { + Thread.sleep(3000); + } + assertThat(r.getReadme(), notNullValue()); + + r.delete(); + } + + private void cleanupUserRepository(final String name) throws IOException { + if (mockGitHub.isUseProxy()) { + cleanupRepository(getUser(getNonRecordingGitHub()).getLogin() + "/" + name); + } } /** - * Directory listing. + * Test credential valid. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void directoryListing() throws IOException { - List children = gitHub.getRepository("jenkinsci/jenkins").getDirectoryContent("core"); - for (GHContent c : children) { - // System.out.println(c.getName()); - if (c.isDirectory()) { - for (GHContent d : c.listDirectoryContent()) { - // System.out.println(" " + d.getName()); - } - } - } + public void testCredentialValid() throws IOException { + assertThat(gitHub.isCredentialValid(), is(true)); + assertThat(gitHub.lastRateLimit().getCore(), not(instanceOf(GHRateLimit.UnknownLimitRecord.class))); + assertThat(gitHub.lastRateLimit().getCore().getLimit(), equalTo(5000)); + + gitHub = getGitHubBuilder().withOAuthToken("bogus", "user") + .withEndpoint(mockGitHub.apiServer().baseUrl()) + .build(); + assertThat(gitHub.lastRateLimit(), sameInstance(GHRateLimit.DEFAULT)); + assertThat(gitHub.isCredentialValid(), is(false)); + // For invalid credentials, we get a 401 but it includes anonymous rate limit headers + assertThat(gitHub.lastRateLimit().getCore(), not(instanceOf(GHRateLimit.UnknownLimitRecord.class))); + assertThat(gitHub.lastRateLimit().getCore().getLimit(), equalTo(60)); } /** - * List org memberships. + * Test credential valid enterprise. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void listOrgMemberships() throws Exception { - GHMyself me = gitHub.getMyself(); - for (GHMembership m : me.listOrgMemberships()) { - assertThat(m.getUser(), is((GHUser) me)); - assertThat(m.getState(), notNullValue()); - assertThat(m.getRole(), notNullValue()); - } + public void testCredentialValidEnterprise() throws IOException { + // Simulated GHE: getRateLimit returns 404 + assertThat(gitHub.lastRateLimit(), sameInstance(GHRateLimit.DEFAULT)); + assertThat(gitHub.lastRateLimit().getCore().isExpired(), is(true)); + assertThat(gitHub.isCredentialValid(), is(true)); + + // lastRateLimitUpdates because 404 still includes header rate limit info + assertThat(gitHub.lastRateLimit(), notNullValue()); + assertThat(gitHub.lastRateLimit(), not(equalTo(GHRateLimit.DEFAULT))); + assertThat(gitHub.lastRateLimit().getCore().isExpired(), is(false)); + + gitHub = getGitHubBuilder().withOAuthToken("bogus", "user") + .withEndpoint(mockGitHub.apiServer().baseUrl()) + .build(); + assertThat(gitHub.lastRateLimit(), sameInstance(GHRateLimit.DEFAULT)); + assertThat(gitHub.isCredentialValid(), is(false)); + // Simulated GHE: For invalid credentials, we get a 401 that does not include ratelimit info + assertThat(gitHub.lastRateLimit(), sameInstance(GHRateLimit.DEFAULT)); } /** - * Notifications. + * Test issue with no comment. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void notifications() throws Exception { - boolean found = false; - for (GHThread t : gitHub.listNotifications().since(0).nonBlocking(true).read(true)) { - if (!found) { - found = true; - // both read and unread are included - assertThat(t.getTitle(), is("Create a Jenkinsfile for Librecores CI in mor1kx")); - assertThat(t.getLastReadAt(), notNullValue()); - assertThat(t.isRead(), equalTo(true)); + public void testIssueWithNoComment() throws IOException { + GHRepository repository = gitHub.getRepository("kohsuke/test"); + GHIssue i = repository.getIssue(4); + List v = i.getComments(); + // System.out.println(v); + assertThat(v, is(empty())); + } - t.markAsRead(); // test this by calling it once on old notfication - } - assertThat(t.getReason(), oneOf("subscribed", "mention", "review_requested", "comment")); - assertThat(t.getTitle(), notNullValue()); - assertThat(t.getLastCommentUrl(), notNullValue()); - assertThat(t.getRepository(), notNullValue()); - assertThat(t.getUpdatedAt(), notNullValue()); - assertThat(t.getType(), oneOf("Issue", "PullRequest")); + /** + * Test issue with comment. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testIssueWithComment() throws IOException { + GHRepository repository = gitHub.getRepository("kohsuke/test"); + GHIssue i = repository.getIssue(3); + List v = i.getComments(); + // System.out.println(v); + assertThat(v.size(), equalTo(3)); + assertThat(v.get(0).getHtmlUrl().toString(), + equalTo("https://github.com/kohsuke/test/issues/3#issuecomment-8547249")); + assertThat(v.get(0).getUrl().toString(), endsWith("/repos/kohsuke/test/issues/comments/8547249")); + assertThat(v.get(0).getNodeId(), equalTo("MDEyOklzc3VlQ29tbWVudDg1NDcyNDk=")); + assertThat(v.get(0).getParent().getNumber(), equalTo(3)); + assertThat(v.get(0).getParent().getId(), equalTo(6863845L)); + assertThat(v.get(0).getUser().getLogin(), equalTo("kohsuke")); + assertThat(v.get(0).listReactions().toList(), is(empty())); - // both thread an unread are included - // assertThat(t.getLastReadAt(), notNullValue()); - // assertThat(t.isRead(), equalTo(true)); + assertThat(v.get(1).getHtmlUrl().toString(), + equalTo("https://github.com/kohsuke/test/issues/3#issuecomment-8547251")); + assertThat(v.get(1).getUrl().toString(), endsWith("/repos/kohsuke/test/issues/comments/8547251")); + assertThat(v.get(1).getNodeId(), equalTo("MDEyOklzc3VlQ29tbWVudDg1NDcyNTE=")); + assertThat(v.get(1).getParent().getNumber(), equalTo(3)); + assertThat(v.get(1).getUser().getLogin(), equalTo("kohsuke")); + List reactions = v.get(1).listReactions().toList(); + assertThat(reactions.size(), equalTo(3)); + assertThat(reactions.stream().map(item -> item.getContent()).collect(Collectors.toList()), + containsInAnyOrder(ReactionContent.EYES, ReactionContent.HOORAY, ReactionContent.ROCKET)); - // Doesn't exist on threads but is part of GHObject. :( - assertThat(t.getCreatedAt(), nullValue()); + // TODO: Add comment CRUD test + GHReaction reaction = null; + try { + reaction = v.get(1).createReaction(ReactionContent.CONFUSED); + v = i.getComments(); + reactions = v.get(1).listReactions().toList(); + assertThat(reactions.stream().map(item -> item.getContent()).collect(Collectors.toList()), + containsInAnyOrder(ReactionContent.CONFUSED, + ReactionContent.EYES, + ReactionContent.HOORAY, + ReactionContent.ROCKET)); + + // test new delete reaction API + v.get(1).deleteReaction(reaction); + reaction = null; + v = i.getComments(); + reactions = v.get(1).listReactions().toList(); + assertThat(reactions.stream().map(item -> item.getContent()).collect(Collectors.toList()), + containsInAnyOrder(ReactionContent.EYES, ReactionContent.HOORAY, ReactionContent.ROCKET)); + } finally { + if (reaction != null) { + v.get(1).deleteReaction(reaction); + reaction = null; + } } - assertThat(found, is(true)); - gitHub.listNotifications().markAsRead(); - gitHub.listNotifications().iterator().next(); } /** - * Reactions. + * Test create issue. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void reactions() throws Exception { - GHIssue i = gitHub.getRepository("hub4j/github-api").getIssue(311); - - // cover issue methods - assertThat(i.getClosedAt(), equalTo(GitHubClient.parseInstant("2016-11-17T02:40:11Z"))); - assertThat(i.getHtmlUrl().toString(), endsWith("github-api/issues/311")); + public void testCreateIssue() throws IOException { + GHUser u = getUser(); + GHRepository repository = getTestRepository(); + GHMilestone milestone = repository.createMilestone("Test Milestone Title3", "Test Milestone"); + GHIssue o = repository.createIssue("testing") + .body("this is body") + .assignee(u) + .label("bug") + .label("question") + .milestone(milestone) + .create(); + assertThat(o, notNullValue()); + assertThat(o.getBody(), equalTo("this is body")); - List l; - // retrieval - l = i.listReactions().toList(); - assertThat(l.size(), equalTo(1)); - - assertThat(l.get(0).getUser().getLogin(), is("kohsuke")); - assertThat(l.get(0).getContent(), is(ReactionContent.HEART)); - - // CRUD - GHReaction a; - a = i.createReaction(ReactionContent.HOORAY); - assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(a.getContent(), is(ReactionContent.HOORAY)); - i.deleteReaction(a); - - l = i.listReactions().toList(); - assertThat(l.size(), equalTo(1)); - - a = i.createReaction(ReactionContent.PLUS_ONE); - assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(a.getContent(), is(ReactionContent.PLUS_ONE)); - - a = i.createReaction(ReactionContent.CONFUSED); - assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(a.getContent(), is(ReactionContent.CONFUSED)); - - a = i.createReaction(ReactionContent.EYES); - assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(a.getContent(), is(ReactionContent.EYES)); - - a = i.createReaction(ReactionContent.ROCKET); - assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(a.getContent(), is(ReactionContent.ROCKET)); - - l = i.listReactions().toList(); - assertThat(l.size(), equalTo(5)); - assertThat(l.get(0).getUser().getLogin(), is("kohsuke")); - assertThat(l.get(0).getContent(), is(ReactionContent.HEART)); - assertThat(l.get(1).getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(l.get(1).getContent(), is(ReactionContent.PLUS_ONE)); - assertThat(l.get(2).getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(l.get(2).getContent(), is(ReactionContent.CONFUSED)); - assertThat(l.get(3).getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(l.get(3).getContent(), is(ReactionContent.EYES)); - assertThat(l.get(4).getUser().getLogin(), is(gitHub.getMyself().getLogin())); - assertThat(l.get(4).getContent(), is(ReactionContent.ROCKET)); - - i.deleteReaction(l.get(1)); - i.deleteReaction(l.get(2)); - i.deleteReaction(l.get(3)); - i.deleteReaction(l.get(4)); + // test locking + assertThat(o.isLocked(), is(false)); + o.lock(); + o = repository.getIssue(o.getNumber()); + assertThat(o.isLocked(), is(true)); + o.unlock(); + o = repository.getIssue(o.getNumber()); + assertThat(o.isLocked(), is(false)); - l = i.listReactions().toList(); - assertThat(l.size(), equalTo(1)); + o.close(); } /** - * Test add deploy key. + * Test create and list deployments. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testAddDeployKey() throws IOException { - GHRepository myRepository = getTestRepository(); - final GHDeployKey newDeployKey = myRepository.addDeployKey("test", - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIATWwMLytklB44O66isWRKOB3Qd7Ysc7q7EyWTmT0bG9 test@example.com"); + public void testCreateAndListDeployments() throws IOException { + GHRepository repository = getTestRepository(); + GHDeployment deployment = repository.createDeployment("main") + .payload("{\"user\":\"atmos\",\"room_id\":123456}") + .description("question") + .environment("unittest") + .create(); try { - assertThat(newDeployKey.getId(), notNullValue()); - - GHDeployKey k = Iterables.find(myRepository.getDeployKeys(), new Predicate() { - public boolean apply(GHDeployKey deployKey) { - return newDeployKey.getId() == deployKey.getId() && !deployKey.isRead_only(); - } - }); - assertThat(k, notNullValue()); + assertThat(deployment.getCreator(), notNullValue()); + assertThat(deployment.getId(), notNullValue()); + List deployments = repository.listDeployments(null, "main", null, "unittest").toList(); + assertThat(deployments, notNullValue()); + assertThat(deployments, is(not(emptyIterable()))); + GHDeployment unitTestDeployment = deployments.get(0); + assertThat(unitTestDeployment.getEnvironment(), equalTo("unittest")); + assertThat(unitTestDeployment.getOriginalEnvironment(), equalTo("unittest")); + assertThat(unitTestDeployment.isProductionEnvironment(), equalTo(false)); + assertThat(unitTestDeployment.isTransientEnvironment(), equalTo(false)); + assertThat(unitTestDeployment.getRef(), equalTo("main")); } finally { - newDeployKey.delete(); + // deployment.delete(); + assert true; } } /** - * Test add deploy key read-only. + * Test get deployment statuses. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testAddDeployKeyAsReadOnly() throws IOException { - GHRepository myRepository = getTestRepository(); - final GHDeployKey newDeployKey = myRepository.addDeployKey("test", - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIATWwMLytklB44O66isWRKOB3Qd7Ysc7q7EyWTmT0bG9 test@example.com", - true); + public void testGetDeploymentStatuses() throws IOException { + GHRepository repository = getTestRepository(); + GHDeployment deployment = repository.createDeployment("main") + .description("question") + .payload("{\"user\":\"atmos\",\"room_id\":123456}") + .create(); try { - assertThat(newDeployKey.getId(), notNullValue()); - - GHDeployKey k = Iterables.find(myRepository.getDeployKeys(), new Predicate() { - public boolean apply(GHDeployKey deployKey) { - return newDeployKey.getId() == deployKey.getId() && deployKey.isRead_only(); - } - }); - assertThat(k, notNullValue()); + GHDeploymentStatus ghDeploymentStatus = deployment.createStatus(GHDeploymentState.QUEUED) + .description("success") + .logUrl("http://www.github.com/logurl") + .environmentUrl("http://www.github.com/envurl") + .environment("new-ci-env") + .create(); + Iterable deploymentStatuses = deployment.listStatuses(); + assertThat(deploymentStatuses, notNullValue()); + assertThat(Iterables.size(deploymentStatuses), equalTo(1)); + GHDeploymentStatus actualStatus = Iterables.get(deploymentStatuses, 0); + assertThat(actualStatus.getId(), equalTo(ghDeploymentStatus.getId())); + assertThat(actualStatus.getState(), equalTo(ghDeploymentStatus.getState())); + assertThat(actualStatus.getLogUrl(), equalTo(ghDeploymentStatus.getLogUrl())); + assertThat(ghDeploymentStatus.getDeploymentUrl(), equalTo(deployment.getUrl())); + assertThat(ghDeploymentStatus.getRepositoryUrl(), equalTo(repository.getUrl())); } finally { - newDeployKey.delete(); + // deployment.delete(); + assert true; } } /** - * Test app. - */ - @Ignore("Needs mocking check") - @Test - public void testApp() { - // System.out.println(gitHub.getMyself().getEmails()); - - // GHRepository r = gitHub.getOrganization("jenkinsci").createRepository("kktest4", "Kohsuke's test", - // "http://kohsuke.org/", "Everyone", true); - // r.fork(); - - // tryDisablingIssueTrackers(gitHub); - - // tryDisablingWiki(gitHub); - - // GHPullRequest i = gitHub.getOrganization("jenkinsci").getRepository("sandbox").getPullRequest(1); - // for (GHIssueComment c : i.getComments()) - // // System.out.println(c); - // // System.out.println(i); - - // gitHub.getMyself().getRepository("perforce-plugin").setEmailServiceHook("kk@kohsuke.org"); - - // tryRenaming(gitHub); - // tryOrgFork(gitHub); - - // testOrganization(gitHub); - // testPostCommitHook(gitHub); - - // tryTeamCreation(gitHub); - - // t.add(gitHub.getMyself()); - // // System.out.println(t.getMembers()); - // t.remove(gitHub.getMyself()); - // // System.out.println(t.getMembers()); - - // GHRepository r = gitHub.getOrganization("HudsonLabs").createRepository("auto-test", "some description", - // "http://kohsuke.org/", "Plugin Developers", true); - - // r. - // GitHub hub = GitHub.connectAnonymously(); - //// hub.createRepository("test","test repository",null,true); - //// hub.getUserTest("kohsuke").getRepository("test").delete(); - // - // // System.out.println(hub.getUserTest("kohsuke").getRepository("hudson").getCollaborators()); - } - - /** - * Test branches. + * Test get issues. * * @throws Exception * the exception */ - @Ignore("Needs mocking check") @Test - public void testBranches() throws Exception { - Map b = gitHub.getUser("jenkinsci").getRepository("jenkins").getBranches(); - // System.out.println(b); + public void testGetIssues() throws Exception { + List closedIssues = gitHub.getOrganization("hub4j") + .getRepository("github-api") + .getIssues(GHIssueState.CLOSED); + // prior to using PagedIterable GHRepository.getIssues(GHIssueState) would only retrieve 30 issues + assertThat(closedIssues.size(), greaterThan(150)); + String readRepoString = GitHub.getMappingObjectWriter().writeValueAsString(closedIssues.get(0)); } /** - * Test check membership. + * Test query issues. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testCheckMembership() throws Exception { - kohsuke(); - GHOrganization j = gitHub.getOrganization("jenkinsci"); - GHUser kohsuke = gitHub.getUser("kohsuke"); - GHUser b = gitHub.getUser("b"); - - assertThat(j.hasMember(kohsuke), is(true)); - assertThat(j.hasMember(b), is(false)); + public void testQueryIssues() throws IOException { + final GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("testQueryIssues"); + List openBugIssues = repo.queryIssues() + .milestone("1") + .creator(gitHub.getMyself().getLogin()) + .state(GHIssueState.OPEN) + .label("bug") + .pageSize(10) + .list() + .toList(); + GHIssue issueWithMilestone = openBugIssues.get(0); + assertThat(openBugIssues, is(not(empty()))); + assertThat(openBugIssues, hasSize(1)); + assertThat(issueWithMilestone.getTitle(), is("Issue with milestone")); + assertThat(issueWithMilestone.getAssignee().getLogin(), is("bloslo")); + assertThat(issueWithMilestone.getBody(), containsString("@bloslo")); - assertThat(j.hasPublicMember(kohsuke), is(true)); - assertThat(j.hasPublicMember(b), is(false)); - } + List openIssuesWithAssignee = repo.queryIssues() + .assignee(gitHub.getMyself().getLogin()) + .state(GHIssueState.OPEN) + .list() + .toList(); + GHIssue issueWithAssignee = openIssuesWithAssignee.get(0); + assertThat(openIssuesWithAssignee, is(not(empty()))); + assertThat(openIssuesWithAssignee, hasSize(1)); + assertThat(issueWithAssignee.getLabels(), hasSize(2)); + assertThat(issueWithAssignee.getMilestone(), is(notNullValue())); - /** - * Test commit. - * - * @throws Exception - * the exception - */ - @Test - public void testCommit() throws Exception { - GHCommit commit = gitHub.getUser("jenkinsci") - .getRepository("jenkins") - .getCommit("08c1c9970af4d609ae754fbe803e06186e3206f7"); - assertThat(commit.getParents().size(), equalTo(1)); - assertThat(commit.listFiles().toList().size(), equalTo(1)); - assertThat(commit.getHtmlUrl().toString(), - equalTo("https://github.com/jenkinsci/jenkins/commit/08c1c9970af4d609ae754fbe803e06186e3206f7")); - assertThat(commit.getLinesAdded(), equalTo(40)); - assertThat(commit.getLinesChanged(), equalTo(48)); - assertThat(commit.getLinesDeleted(), equalTo(8)); - assertThat(commit.getParentSHA1s().size(), equalTo(1)); - assertThat(commit.getAuthoredDate(), equalTo(GitHubClient.parseInstant("2012-04-24T00:16:52Z"))); - assertThat(commit.getCommitDate(), equalTo(GitHubClient.parseInstant("2012-04-24T00:16:52Z"))); - assertThat(commit.getCommitShortInfo().getCommentCount(), equalTo(0)); - assertThat(commit.getCommitShortInfo().getAuthoredDate(), equalTo(commit.getAuthoredDate())); - assertThat(commit.getCommitShortInfo().getCommitDate(), equalTo(commit.getCommitDate())); - assertThat(commit.getCommitShortInfo().getMessage(), equalTo("creating an RC branch")); + List allIssuesSince = repo.queryIssues() + .mentioned(gitHub.getMyself().getLogin()) + .state(GHIssueState.ALL) + .since(1632411646L) + .sort(GHIssueQueryBuilder.Sort.COMMENTS) + .direction(GHDirection.ASC) + .list() + .toList(); + GHIssue issueSince = allIssuesSince.get(3); + assertThat(allIssuesSince, is(not(empty()))); + assertThat(allIssuesSince, hasSize(4)); + assertThat(issueSince.getBody(), is("Test closed issue @bloslo")); + assertThat(issueSince.getState(), is(GHIssueState.CLOSED)); - File f = commit.listFiles().toList().get(0); - assertThat(f.getLinesChanged(), equalTo(48)); - assertThat(f.getLinesAdded(), equalTo(40)); - assertThat(f.getLinesDeleted(), equalTo(8)); - assertThat(f.getPreviousFilename(), nullValue()); - assertThat(f.getPatch(), startsWith("@@ -54,6 +54,14 @@\n")); - assertThat(f.getSha(), equalTo("04d3e54017542ad0ff46355eababacd4850ccba5")); - assertThat(f.getBlobUrl().toString(), - equalTo("https://github.com/jenkinsci/jenkins/blob/08c1c9970af4d609ae754fbe803e06186e3206f7/changelog.html")); - assertThat(f.getRawUrl().toString(), - equalTo("https://github.com/jenkinsci/jenkins/raw/08c1c9970af4d609ae754fbe803e06186e3206f7/changelog.html")); + List allIssuesWithLabels = repo.queryIssues() + .label("bug") + .label("test-label") + .state(GHIssueState.ALL) + .list() + .toList(); + GHIssue issueWithLabel = allIssuesWithLabels.get(0); + assertThat(allIssuesWithLabels, is(not(empty()))); + assertThat(allIssuesWithLabels, hasSize(5)); + assertThat(issueWithLabel.getComments(), hasSize(2)); + assertThat(issueWithLabel.getTitle(), is("Issue with comments")); - assertThat(f.getStatus(), equalTo("modified")); - assertThat(f.getFileName(), equalTo("changelog.html")); + List issuesWithLabelNull = repo.queryIssues().label(null).list().toList(); + GHIssue issueWithLabelNull = issuesWithLabelNull.get(2); + assertThat(issuesWithLabelNull, is(not(empty()))); + assertThat(issuesWithLabelNull, hasSize(6)); + assertThat(issueWithLabelNull.getTitle(), is("Closed issue")); + assertThat(issueWithLabelNull.getBody(), is("Test closed issue @bloslo")); + assertThat(issueWithLabelNull.getState(), is(GHIssueState.OPEN)); - // walk the tree - GHTree t = commit.getTree(); - assertThat(IOUtils.toString(t.getEntry("todo.txt").readAsBlob()), containsString("executor rendering")); - assertThat(t.getEntry("war").asTree(), notNullValue()); + List issuesWithLabelEmptyString = repo.queryIssues().label("").state(GHIssueState.ALL).list().toList(); + GHIssue issueWithLabelEmptyString = issuesWithLabelEmptyString.get(0); + assertThat(issuesWithLabelEmptyString, is(not(empty()))); + assertThat(issuesWithLabelEmptyString, hasSize(8)); + assertThat(issueWithLabelEmptyString.getTitle(), is("Closed issue")); + assertThat(issueWithLabelEmptyString.getBody(), is("Test closed issue @bloslo")); } - /** - * Test commit comment. - * - * @throws Exception - * the exception - */ - @Test - public void testCommitComment() throws Exception { - GHRepository r = gitHub.getUser("jenkinsci").getRepository("jenkins"); - PagedIterable comments = r.listCommitComments(); - List batch = comments.iterator().nextPage(); - for (GHCommitComment comment : batch) { - // System.out.println(comment.getBody()); - assertThat(r, sameInstance(comment.getOwner())); - } + private GHRepository getTestRepository() throws IOException { + return getTempRepository(GITHUB_API_TEST_REPO); } /** - * Test commit search. + * Test list issues. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCommitSearch() throws IOException { - PagedSearchIterable r = gitHub.searchCommits() - .org("github-api") - .repo("github-api") - .author("kohsuke") - .sort(GHCommitSearchBuilder.Sort.COMMITTER_DATE) + public void testListIssues() throws IOException { + Iterable closedIssues = gitHub.getOrganization("hub4j") + .getRepository("github-api") + .queryIssues() + .state(GHIssueState.CLOSED) .list(); - assertThat(r.getTotalCount(), greaterThan(0)); - - GHCommit firstCommit = r.iterator().next(); - assertThat(firstCommit.listFiles().toList(), is(not(empty()))); - } - - /** - * Test commit short info. - * - * @throws Exception - * the exception - */ - @Test - public void testCommitShortInfo() throws Exception { - GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f23"); - assertThat("Kohsuke Kawaguchi", equalTo(commit.getCommitShortInfo().getAuthor().getName())); - assertThat("doc", equalTo(commit.getCommitShortInfo().getMessage())); - assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(GHVerification.Reason.UNSIGNED, equalTo(commit.getCommitShortInfo().getVerification().getReason())); - assertThat(commit.getCommitShortInfo().getAuthor().getDate().getEpochSecond(), equalTo(1271650361L)); - assertThat(commit.getCommitShortInfo().getCommitter().getDate().getEpochSecond(), equalTo(1271650361L)); - } - - /** - * Test commit status. - * - * @throws Exception - * the exception - */ - @Test - public void testCommitStatus() throws Exception { - GHRepository r = gitHub.getRepository("hub4j/github-api"); - - GHCommitStatus state; - // state = r.createCommitStatus("ecbfdd7315ef2cf04b2be7f11a072ce0bd00c396", GHCommitState.FAILURE, - // "http://kohsuke.org/", "testing!"); + int x = 0; + for (GHIssue issue : closedIssues) { + assertThat(issue, notNullValue()); + x++; + } - List lst = r.listCommitStatuses("ecbfdd7315ef2cf04b2be7f11a072ce0bd00c396").toList(); - state = lst.get(0); - // System.out.println(state); - assertThat(state.getDescription(), equalTo("testing!")); - assertThat(state.getTargetUrl(), equalTo("http://kohsuke.org/")); - assertThat(state.getCreator().getLogin(), equalTo("kohsuke")); + assertThat(x, greaterThan(150)); } /** - * Test commit status context. + * Test rate limit. * * @throws IOException * Signals that an I/O exception has occurred. */ - @Ignore("Needs mocking check") @Test - public void testCommitStatusContext() throws IOException { - GHRepository myRepository = getTestRepository(); - GHRef mainRef = myRepository.getRef("heads/main"); - GHCommitStatus commitStatus = myRepository.createCommitStatus(mainRef.getObject() - .getSha(), GHCommitState.SUCCESS, "http://www.example.com", "test", "test/context"); - assertThat(commitStatus.getContext(), equalTo("test/context")); - + public void testRateLimit() throws IOException { + assertThat(gitHub.getRateLimit(), notNullValue()); } /** - * Test create and list deployments. + * Test my organizations. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCreateAndListDeployments() throws IOException { - GHRepository repository = getTestRepository(); - GHDeployment deployment = repository.createDeployment("main") - .payload("{\"user\":\"atmos\",\"room_id\":123456}") - .description("question") - .environment("unittest") - .create(); - try { - assertThat(deployment.getCreator(), notNullValue()); - assertThat(deployment.getId(), notNullValue()); - List deployments = repository.listDeployments(null, "main", null, "unittest").toList(); - assertThat(deployments, notNullValue()); - assertThat(deployments, is(not(emptyIterable()))); - GHDeployment unitTestDeployment = deployments.get(0); - assertThat(unitTestDeployment.getEnvironment(), equalTo("unittest")); - assertThat(unitTestDeployment.getOriginalEnvironment(), equalTo("unittest")); - assertThat(unitTestDeployment.isProductionEnvironment(), equalTo(false)); - assertThat(unitTestDeployment.isTransientEnvironment(), equalTo(false)); - assertThat(unitTestDeployment.getRef(), equalTo("main")); - } finally { - // deployment.delete(); - assert true; - } + public void testMyOrganizations() throws IOException { + Map org = gitHub.getMyOrganizations(); + assertThat(org.containsKey(null), is(false)); + // System.out.println(org); } /** - * Test create commit comment. + * Test my organizations contain my teams. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testCreateCommitComment() throws Exception { - GHCommit commit = gitHub.getUser("kohsuke") - .getRepository("sandbox-ant") - .getCommit("8ae38db0ea5837313ab5f39d43a6f73de3bd9000"); - - assertThat(commit.getCommitShortInfo().getCommentCount(), equalTo(30)); - GHCommitComment c = commit.createComment("[testing](http://kohsuse.org/)"); - try { - assertThat(c.getPath(), nullValue()); - assertThat(c.getLine(), equalTo(-1)); - assertThat(c.getHtmlUrl().toString(), - containsString( - "kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000#commitcomment-")); - assertThat(c.listReactions().toList(), is(empty())); - - c.update("updated text"); - assertThat(c.getBody(), equalTo("updated text")); - - commit = gitHub.getUser("kohsuke") - .getRepository("sandbox-ant") - .getCommit("8ae38db0ea5837313ab5f39d43a6f73de3bd9000"); - - assertThat(commit.getCommitShortInfo().getCommentCount(), equalTo(31)); - - // testing reactions - List reactions = c.listReactions().toList(); - assertThat(reactions, is(empty())); - - GHReaction reaction = c.createReaction(ReactionContent.CONFUSED); - assertThat(reaction.getContent(), equalTo(ReactionContent.CONFUSED)); - - reactions = c.listReactions().toList(); - assertThat(reactions.size(), equalTo(1)); - - c.deleteReaction(reaction); - - reactions = c.listReactions().toList(); - assertThat(reactions.size(), equalTo(0)); - } finally { - c.delete(); - } + public void testMyOrganizationsContainMyTeams() throws IOException { + Map> teams = gitHub.getMyTeams(); + Map myOrganizations = gitHub.getMyOrganizations(); + // GitHub no longer has default 'owners' team, so there may be organization memberships without a team + // https://help.github.com/articles/about-improved-organization-permissions/ + assertThat(myOrganizations.keySet().containsAll(teams.keySet()), is(true)); } /** - * Test create issue. + * Test my teams should include myself. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCreateIssue() throws IOException { - GHUser u = getUser(); - GHRepository repository = getTestRepository(); - GHMilestone milestone = repository.createMilestone("Test Milestone Title3", "Test Milestone"); - GHIssue o = repository.createIssue("testing") - .body("this is body") - .assignee(u) - .label("bug") - .label("question") - .milestone(milestone) - .create(); - assertThat(o, notNullValue()); - assertThat(o.getBody(), equalTo("this is body")); - - // test locking - assertThat(o.isLocked(), is(false)); - o.lock(); - o = repository.getIssue(o.getNumber()); - assertThat(o.isLocked(), is(true)); - o.unlock(); - o = repository.getIssue(o.getNumber()); - assertThat(o.isLocked(), is(false)); - - o.close(); + public void testMyTeamsShouldIncludeMyself() throws IOException { + Map> teams = gitHub.getMyTeams(); + for (Entry> teamsPerOrg : teams.entrySet()) { + String organizationName = teamsPerOrg.getKey(); + for (GHTeam team : teamsPerOrg.getValue()) { + String teamName = team.getName(); + assertThat("Team " + teamName + " in organization " + organizationName + " does not contain myself", + shouldBelongToTeam(organizationName, teamName)); + } + } } /** - * Test credential valid. + * Test user public organizations when there are some. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCredentialValid() throws IOException { - assertThat(gitHub.isCredentialValid(), is(true)); - assertThat(gitHub.lastRateLimit().getCore(), not(instanceOf(GHRateLimit.UnknownLimitRecord.class))); - assertThat(gitHub.lastRateLimit().getCore().getLimit(), equalTo(5000)); + public void testUserPublicOrganizationsWhenThereAreSome() throws IOException { + // kohsuke had some public org memberships at the time Wiremock recorded the GitHub API responses + GHUser user = new GHUser(); + user.login = "kohsuke"; - gitHub = getGitHubBuilder().withOAuthToken("bogus", "user") - .withEndpoint(mockGitHub.apiServer().baseUrl()) - .build(); - assertThat(gitHub.lastRateLimit(), sameInstance(GHRateLimit.DEFAULT)); - assertThat(gitHub.isCredentialValid(), is(false)); - // For invalid credentials, we get a 401 but it includes anonymous rate limit headers - assertThat(gitHub.lastRateLimit().getCore(), not(instanceOf(GHRateLimit.UnknownLimitRecord.class))); - assertThat(gitHub.lastRateLimit().getCore().getLimit(), equalTo(60)); + Map orgs = gitHub.getUserPublicOrganizations(user); + assertThat(orgs.size(), greaterThan(0)); } /** - * Test credential valid enterprise. + * Test user public organizations when there are none. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCredentialValidEnterprise() throws IOException { - // Simulated GHE: getRateLimit returns 404 - assertThat(gitHub.lastRateLimit(), sameInstance(GHRateLimit.DEFAULT)); - assertThat(gitHub.lastRateLimit().getCore().isExpired(), is(true)); - assertThat(gitHub.isCredentialValid(), is(true)); + public void testUserPublicOrganizationsWhenThereAreNone() throws IOException { + // bitwiseman had no public org memberships at the time Wiremock recorded the GitHub API responses + GHUser user = new GHUser(); + user.login = "bitwiseman"; - // lastRateLimitUpdates because 404 still includes header rate limit info - assertThat(gitHub.lastRateLimit(), notNullValue()); - assertThat(gitHub.lastRateLimit(), not(equalTo(GHRateLimit.DEFAULT))); - assertThat(gitHub.lastRateLimit().getCore().isExpired(), is(false)); + Map orgs = gitHub.getUserPublicOrganizations(user); + assertThat(orgs.size(), equalTo(0)); + } - gitHub = getGitHubBuilder().withOAuthToken("bogus", "user") - .withEndpoint(mockGitHub.apiServer().baseUrl()) - .build(); - assertThat(gitHub.lastRateLimit(), sameInstance(GHRateLimit.DEFAULT)); - assertThat(gitHub.isCredentialValid(), is(false)); - // Simulated GHE: For invalid credentials, we get a 401 that does not include ratelimit info - assertThat(gitHub.lastRateLimit(), sameInstance(GHRateLimit.DEFAULT)); + private boolean shouldBelongToTeam(String organizationName, String teamName) throws IOException { + GHOrganization org = gitHub.getOrganization(organizationName); + assertThat(org, notNullValue()); + GHTeam team = org.getTeamByName(teamName); + assertThat(team, notNullValue()); + return team.hasMember(gitHub.getMyself()); } /** - * Test event api. + * Test should fetch team from organization. * * @throws Exception * the exception */ @Test - public void testEventApi() throws Exception { - for (GHEventInfo ev : gitHub.getEvents()) { - if (ev.getType() == GHEvent.PULL_REQUEST) { - GHEventPayload.PullRequest pr = ev.getPayload(GHEventPayload.PullRequest.class); - assertThat(pr.getNumber(), is(pr.getPullRequest().getNumber())); + public void testShouldFetchTeamFromOrganization() throws Exception { + GHOrganization organization = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHTeam teamByName = organization.getTeams().get("Core Developers"); - assertThat(pr.getPullRequest().getClosedBy(), nullValue()); - assertThat(pr.getPullRequest().getPullRequest(), nullValue()); + GHTeam teamById = organization.getTeam(teamByName.getId()); + assertThat(teamById, notNullValue()); + + assertThat(teamById.getId(), equalTo(teamByName.getId())); + assertThat(teamById.getDescription(), equalTo(teamByName.getDescription())); + + GHTeam teamById2 = organization.getTeam(teamByName.getId()); + assertThat(teamById2, notNullValue()); + + assertThat(teamById2.getId(), equalTo(teamByName.getId())); + assertThat(teamById2.getDescription(), equalTo(teamByName.getDescription())); - if (ev.getId() == 10680625394L) { - assertThat(ev.getActorLogin(), equalTo("pull[bot]")); - assertThat(ev.getOrganization(), nullValue()); - assertThat(ev.getRepository().getFullName(), equalTo("daddyfatstacksBIG/lerna")); - assertThat(ev.getCreatedAt(), equalTo(GitHubClient.parseInstant("2019-10-21T21:54:52Z"))); - assertThat(ev.getType(), equalTo(GHEvent.PULL_REQUEST)); - assertThat(pr.getPullRequest().getMergedAt(), - equalTo(GitHubClient.parseInstant("2019-10-21T21:54:52Z"))); - assertThat(pr.getPullRequest().getPatchUrl().toString(), endsWith("lerna/pull/20.patch")); - assertThat(pr.getPullRequest().getDiffUrl().toString(), endsWith("lerna/pull/20.diff")); - } - } - } } /** @@ -740,446 +638,788 @@ public void testGetAppInstallations() throws Exception { } /** - * Test get deployment statuses. + * Test repo permissions. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ + @Ignore("Needs mocking check") @Test - public void testGetDeploymentStatuses() throws IOException { - GHRepository repository = getTestRepository(); - GHDeployment deployment = repository.createDeployment("main") - .description("question") - .payload("{\"user\":\"atmos\",\"room_id\":123456}") - .create(); - try { - GHDeploymentStatus ghDeploymentStatus = deployment.createStatus(GHDeploymentState.QUEUED) - .description("success") - .logUrl("http://www.github.com/logurl") - .environmentUrl("http://www.github.com/envurl") - .environment("new-ci-env") - .create(); - Iterable deploymentStatuses = deployment.listStatuses(); - assertThat(deploymentStatuses, notNullValue()); - assertThat(Iterables.size(deploymentStatuses), equalTo(1)); - GHDeploymentStatus actualStatus = Iterables.get(deploymentStatuses, 0); - assertThat(actualStatus.getId(), equalTo(ghDeploymentStatus.getId())); - assertThat(actualStatus.getState(), equalTo(ghDeploymentStatus.getState())); - assertThat(actualStatus.getLogUrl(), equalTo(ghDeploymentStatus.getLogUrl())); - assertThat(ghDeploymentStatus.getDeploymentUrl(), equalTo(deployment.getUrl())); - assertThat(ghDeploymentStatus.getRepositoryUrl(), equalTo(repository.getUrl())); - assertThat(ghDeploymentStatus.getEnvironmentUrl().toString(), equalTo("http://www.github.com/envurl")); + public void testRepoPermissions() throws Exception { + kohsuke(); - } finally { - // deployment.delete(); - assert true; + GHRepository r = gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("github-api"); + assertThat(r.hasPullAccess(), is(true)); + + r = gitHub.getOrganization("github").getRepository("hub"); + assertThat(r.hasAdminAccess(), is(false)); + } + + /** + * Test get myself. + * + * @throws Exception + * the exception + */ + @Test + public void testGetMyself() throws Exception { + GHMyself me = gitHub.getMyself(); + assertThat(me, notNullValue()); + assertThat(me.root(), sameInstance(gitHub)); + assertThat(gitHub.getUser("bitwiseman"), notNullValue()); + PagedIterable ghRepositories = me.listRepositories(); + assertThat(ghRepositories, is(not(emptyIterable()))); + } + + /** + * Test public keys. + * + * @throws Exception + * the exception + */ + @Ignore("Needs mocking check") + @Test + public void testPublicKeys() throws Exception { + List keys = gitHub.getMyself().getPublicKeys(); + assertThat(keys, is(not(empty()))); + } + + /** + * Test org fork. + * + * @throws Exception + * the exception + */ + @Test + public void testOrgFork() throws Exception { + cleanupRepository(GITHUB_API_TEST_ORG + "/rubywm"); + gitHub.getRepository("kohsuke/rubywm").forkTo(gitHub.getOrganization(GITHUB_API_TEST_ORG)); + } + + /** + * Test get teams for repo. + * + * @throws Exception + * the exception + */ + @Test + public void testGetTeamsForRepo() throws Exception { + kohsuke(); + // 'Core Developers' and 'Owners' + assertThat(gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("testGetTeamsForRepo").getTeams().size(), + equalTo(2)); + } + + /** + * Test membership. + * + * @throws Exception + * the exception + */ + @Test + public void testMembership() throws Exception { + Set members = gitHub.getOrganization(GITHUB_API_TEST_ORG) + .getRepository("jenkins") + .getCollaboratorNames(); + // System.out.println(members.contains("kohsuke")); + } + + /** + * Test member orgs. + * + * @throws Exception + * the exception + */ + @Test + public void testMemberOrgs() throws Exception { + HashSet o = gitHub.getUser("kohsuke").getOrganizations(); + assertThat(o, hasItem(hasProperty("name", equalTo("CloudBees")))); + } + + /** + * Test org teams. + * + * @throws Exception + * the exception + */ + @Test + public void testOrgTeams() throws Exception { + kohsuke(); + int sz = 0; + for (GHTeam t : gitHub.getOrganization(GITHUB_API_TEST_ORG).listTeams()) { + assertThat(t.getName(), notNullValue()); + sz++; } + assertThat(sz, lessThan(100)); + } + + /** + * Test org team by name. + * + * @throws Exception + * the exception + */ + @Test + public void testOrgTeamByName() throws Exception { + kohsuke(); + GHTeam e = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamByName("Core Developers"); + assertThat(e, notNullValue()); + } + + /** + * Test org team by slug. + * + * @throws Exception + * the exception + */ + @Test + public void testOrgTeamBySlug() throws Exception { + kohsuke(); + GHTeam e = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug("core-developers"); + assertThat(e, notNullValue()); + } + + /** + * Test commit. + * + * @throws Exception + * the exception + */ + @Test + public void testCommit() throws Exception { + GHCommit commit = gitHub.getUser("jenkinsci") + .getRepository("jenkins") + .getCommit("08c1c9970af4d609ae754fbe803e06186e3206f7"); + assertThat(commit.getParents().size(), equalTo(1)); + assertThat(commit.listFiles().toList().size(), equalTo(1)); + assertThat(commit.getHtmlUrl().toString(), + equalTo("https://github.com/jenkinsci/jenkins/commit/08c1c9970af4d609ae754fbe803e06186e3206f7")); + assertThat(commit.getLinesAdded(), equalTo(40)); + assertThat(commit.getLinesChanged(), equalTo(48)); + assertThat(commit.getLinesDeleted(), equalTo(8)); + assertThat(commit.getParentSHA1s().size(), equalTo(1)); + assertThat(commit.getAuthoredDate(), equalTo(GitHubClient.parseDate("2012-04-24T00:16:52Z"))); + assertThat(commit.getCommitDate(), equalTo(GitHubClient.parseDate("2012-04-24T00:16:52Z"))); + assertThat(commit.getCommitShortInfo().getCommentCount(), equalTo(0)); + assertThat(commit.getCommitShortInfo().getAuthoredDate(), equalTo(commit.getAuthoredDate())); + assertThat(commit.getCommitShortInfo().getCommitDate(), equalTo(commit.getCommitDate())); + assertThat(commit.getCommitShortInfo().getMessage(), equalTo("creating an RC branch")); + + File f = commit.listFiles().toList().get(0); + assertThat(f.getLinesChanged(), equalTo(48)); + assertThat(f.getLinesAdded(), equalTo(40)); + assertThat(f.getLinesDeleted(), equalTo(8)); + assertThat(f.getPreviousFilename(), nullValue()); + assertThat(f.getPatch(), startsWith("@@ -54,6 +54,14 @@\n")); + assertThat(f.getSha(), equalTo("04d3e54017542ad0ff46355eababacd4850ccba5")); + assertThat(f.getBlobUrl().toString(), + equalTo("https://github.com/jenkinsci/jenkins/blob/08c1c9970af4d609ae754fbe803e06186e3206f7/changelog.html")); + assertThat(f.getRawUrl().toString(), + equalTo("https://github.com/jenkinsci/jenkins/raw/08c1c9970af4d609ae754fbe803e06186e3206f7/changelog.html")); + + assertThat(f.getStatus(), equalTo("modified")); + assertThat(f.getFileName(), equalTo("changelog.html")); + + // walk the tree + GHTree t = commit.getTree(); + assertThat(IOUtils.toString(t.getEntry("todo.txt").readAsBlob()), containsString("executor rendering")); + assertThat(t.getEntry("war").asTree(), notNullValue()); } /** - * Test getEmails. + * Test list commits. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void testGetEmails() throws IOException { - List emails = gitHub.getMyself().getEmails(); - assertThat(emails.size(), equalTo(2)); - assertThat(emails, contains("bitwiseman@gmail.com", "bitwiseman@users.noreply.github.com")); + public void testListCommits() throws Exception { + List sha1 = new ArrayList(); + for (GHCommit c : gitHub.getUser("kohsuke").getRepository("empty-commit").listCommits()) { + sha1.add(c.getSHA1()); + } + assertThat(sha1.get(0), equalTo("fdfad6be4db6f96faea1f153fb447b479a7a9cb7")); + assertThat(sha1.size(), equalTo(1)); } /** - * Test get issues. + * Test branches. * * @throws Exception * the exception */ + @Ignore("Needs mocking check") @Test - public void testGetIssues() throws Exception { - List closedIssues = gitHub.getOrganization("hub4j") - .getRepository("github-api") - .getIssues(GHIssueState.CLOSED); - // prior to using PagedIterable GHRepository.getIssues(GHIssueState) would only retrieve 30 issues - assertThat(closedIssues.size(), greaterThan(150)); - String readRepoString = GitHub.getMappingObjectWriter().writeValueAsString(closedIssues.get(0)); + public void testBranches() throws Exception { + Map b = gitHub.getUser("jenkinsci").getRepository("jenkins").getBranches(); + // System.out.println(b); } /** - * Test get myself. + * Test commit comment. * * @throws Exception * the exception */ @Test - public void testGetMyself() throws Exception { - GHMyself me = gitHub.getMyself(); - assertThat(me, notNullValue()); - assertThat(me.root(), sameInstance(gitHub)); - assertThat(gitHub.getUser("bitwiseman"), notNullValue()); - PagedIterable ghRepositories = me.listRepositories(); - assertThat(ghRepositories, is(not(emptyIterable()))); + public void testCommitComment() throws Exception { + GHRepository r = gitHub.getUser("jenkinsci").getRepository("jenkins"); + PagedIterable comments = r.listCommitComments(); + List batch = comments.iterator().nextPage(); + for (GHCommitComment comment : batch) { + // System.out.println(comment.getBody()); + assertThat(r, sameInstance(comment.getOwner())); + } } /** - * Test get teams for repo. + * Test create commit comment. * * @throws Exception * the exception */ @Test - public void testGetTeamsForRepo() throws Exception { - kohsuke(); - // 'Core Developers' and 'Owners' - assertThat(gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("testGetTeamsForRepo").getTeams().size(), - equalTo(2)); + public void testCreateCommitComment() throws Exception { + GHCommit commit = gitHub.getUser("kohsuke") + .getRepository("sandbox-ant") + .getCommit("8ae38db0ea5837313ab5f39d43a6f73de3bd9000"); + + assertThat(commit.getCommitShortInfo().getCommentCount(), equalTo(30)); + GHCommitComment c = commit.createComment("[testing](http://kohsuse.org/)"); + try { + assertThat(c.getPath(), nullValue()); + assertThat(c.getLine(), equalTo(-1)); + assertThat(c.getHtmlUrl().toString(), + containsString( + "kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000#commitcomment-")); + assertThat(c.listReactions().toList(), is(empty())); + + c.update("updated text"); + assertThat(c.getBody(), equalTo("updated text")); + + commit = gitHub.getUser("kohsuke") + .getRepository("sandbox-ant") + .getCommit("8ae38db0ea5837313ab5f39d43a6f73de3bd9000"); + + assertThat(commit.getCommitShortInfo().getCommentCount(), equalTo(31)); + + // testing reactions + List reactions = c.listReactions().toList(); + assertThat(reactions, is(empty())); + + GHReaction reaction = c.createReaction(ReactionContent.CONFUSED); + assertThat(reaction.getContent(), equalTo(ReactionContent.CONFUSED)); + + reactions = c.listReactions().toList(); + assertThat(reactions.size(), equalTo(1)); + + c.deleteReaction(reaction); + + reactions = c.listReactions().toList(); + assertThat(reactions.size(), equalTo(0)); + } finally { + c.delete(); + } } /** - * Test issue search. + * Try hook. + * + * @throws Exception + * the exception */ @Test - public void testIssueSearch() { - PagedSearchIterable r = gitHub.searchIssues() - .mentions("kohsuke") - .isOpen() - .sort(GHIssueSearchBuilder.Sort.UPDATED) - .list(); - assertThat(r.getTotalCount(), greaterThan(0)); - for (GHIssue issue : r) { - assertThat(issue.getTitle(), notNullValue()); - PagedIterable comments = issue.listComments(); - for (GHIssueComment comment : comments) { - assertThat(comment, notNullValue()); + public void tryHook() throws Exception { + final GHOrganization o = gitHub.getOrganization(GITHUB_API_TEST_ORG); + final GHRepository r = o.getRepository("github-api"); + try { + GHHook hook = r.createWebHook(new URL("http://www.google.com/")); + assertThat(hook.getName(), equalTo("web")); + assertThat(hook.getEvents().size(), equalTo(1)); + assertThat(hook.getEvents(), contains(GHEvent.PUSH)); + assertThat(hook.getConfig().size(), equalTo(3)); + assertThat(hook.isActive(), equalTo(true)); + + GHHook hook2 = r.getHook((int) hook.getId()); + assertThat(hook2.getName(), equalTo("web")); + assertThat(hook2.getEvents().size(), equalTo(1)); + assertThat(hook2.getEvents(), contains(GHEvent.PUSH)); + assertThat(hook2.getConfig().size(), equalTo(3)); + assertThat(hook2.isActive(), equalTo(true)); + hook2.ping(); + hook2.delete(); + final GHHook finalRepoHook = hook; + GHFileNotFoundException e = Assert.assertThrows(GHFileNotFoundException.class, + () -> r.getHook((int) finalRepoHook.getId())); + assertThat(e.getMessage(), + containsString("repos/hub4j-test-org/github-api/hooks/" + finalRepoHook.getId())); + assertThat(e.getMessage(), containsString("rest/reference/repos#get-a-repository-webhook")); + + hook = r.createWebHook(new URL("http://www.google.com/")); + r.deleteHook((int) hook.getId()); + + hook = o.createWebHook(new URL("http://www.google.com/")); + assertThat(hook.getName(), equalTo("web")); + assertThat(hook.getEvents().size(), equalTo(1)); + assertThat(hook.getEvents(), contains(GHEvent.PUSH)); + assertThat(hook.getConfig().size(), equalTo(3)); + assertThat(hook.isActive(), equalTo(true)); + + hook2 = o.getHook((int) hook.getId()); + assertThat(hook2.getName(), equalTo("web")); + assertThat(hook2.getEvents().size(), equalTo(1)); + assertThat(hook2.getEvents(), contains(GHEvent.PUSH)); + assertThat(hook2.getConfig().size(), equalTo(3)); + assertThat(hook2.isActive(), equalTo(true)); + hook2.ping(); + hook2.delete(); + + final GHHook finalOrgHook = hook; + GHFileNotFoundException e2 = Assert.assertThrows(GHFileNotFoundException.class, + () -> o.getHook((int) finalOrgHook.getId())); + assertThat(e2.getMessage(), containsString("orgs/hub4j-test-org/hooks/" + finalOrgHook.getId())); + assertThat(e2.getMessage(), containsString("rest/reference/orgs#get-an-organization-webhook")); + + hook = o.createWebHook(new URL("http://www.google.com/")); + o.deleteHook((int) hook.getId()); + + // System.out.println(hook); + } finally { + if (mockGitHub.isUseProxy()) { + GHRepository cleanupRepo = getNonRecordingGitHub().getOrganization(GITHUB_API_TEST_ORG) + .getRepository("github-api"); + for (GHHook h : cleanupRepo.getHooks()) { + h.delete(); + } } } } /** - * Test issue with comment. + * Test event api. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void testIssueWithComment() throws IOException { - GHRepository repository = gitHub.getRepository("kohsuke/test"); - GHIssue i = repository.getIssue(3); - List v = i.getComments(); - // System.out.println(v); - assertThat(v.size(), equalTo(3)); - assertThat(v.get(0).getHtmlUrl().toString(), - equalTo("https://github.com/kohsuke/test/issues/3#issuecomment-8547249")); - assertThat(v.get(0).getUrl().toString(), endsWith("/repos/kohsuke/test/issues/comments/8547249")); - assertThat(v.get(0).getNodeId(), equalTo("MDEyOklzc3VlQ29tbWVudDg1NDcyNDk=")); - assertThat(v.get(0).getParent().getNumber(), equalTo(3)); - assertThat(v.get(0).getParent().getId(), equalTo(6863845L)); - assertThat(v.get(0).getUser().getLogin(), equalTo("kohsuke")); - assertThat(v.get(0).listReactions().toList(), is(empty())); - - assertThat(v.get(1).getHtmlUrl().toString(), - equalTo("https://github.com/kohsuke/test/issues/3#issuecomment-8547251")); - assertThat(v.get(1).getUrl().toString(), endsWith("/repos/kohsuke/test/issues/comments/8547251")); - assertThat(v.get(1).getNodeId(), equalTo("MDEyOklzc3VlQ29tbWVudDg1NDcyNTE=")); - assertThat(v.get(1).getParent().getNumber(), equalTo(3)); - assertThat(v.get(1).getUser().getLogin(), equalTo("kohsuke")); - List reactions = v.get(1).listReactions().toList(); - assertThat(reactions.size(), equalTo(3)); - assertThat(reactions.stream().map(item -> item.getContent()).collect(Collectors.toList()), - containsInAnyOrder(ReactionContent.EYES, ReactionContent.HOORAY, ReactionContent.ROCKET)); - - // TODO: Add comment CRUD test + public void testEventApi() throws Exception { + for (GHEventInfo ev : gitHub.getEvents()) { + if (ev.getType() == GHEvent.PULL_REQUEST) { + if (ev.getId() == 10680625394L) { + assertThat(ev.getActorLogin(), equalTo("pull[bot]")); + assertThat(ev.getOrganization(), nullValue()); + assertThat(ev.getRepository().getFullName(), equalTo("daddyfatstacksBIG/lerna")); + assertThat(ev.getCreatedAt(), equalTo(GitHubClient.parseDate("2019-10-21T21:54:52Z"))); + assertThat(ev.getType(), equalTo(GHEvent.PULL_REQUEST)); + } - GHReaction reaction = null; - try { - reaction = v.get(1).createReaction(ReactionContent.CONFUSED); - v = i.getComments(); - reactions = v.get(1).listReactions().toList(); - assertThat(reactions.stream().map(item -> item.getContent()).collect(Collectors.toList()), - containsInAnyOrder(ReactionContent.CONFUSED, - ReactionContent.EYES, - ReactionContent.HOORAY, - ReactionContent.ROCKET)); + GHEventPayload.PullRequest pr = ev.getPayload(GHEventPayload.PullRequest.class); + assertThat(pr.getNumber(), is(pr.getPullRequest().getNumber())); + } + } + } - // test new delete reaction API - v.get(1).deleteReaction(reaction); - reaction = null; - v = i.getComments(); - reactions = v.get(1).listReactions().toList(); - assertThat(reactions.stream().map(item -> item.getContent()).collect(Collectors.toList()), - containsInAnyOrder(ReactionContent.EYES, ReactionContent.HOORAY, ReactionContent.ROCKET)); - } finally { - if (reaction != null) { - v.get(1).deleteReaction(reaction); - reaction = null; + /** + * Test user public event api. + * + * @throws Exception + * the exception + */ + @Test + public void testUserPublicEventApi() throws Exception { + for (GHEventInfo ev : gitHub.getUserPublicEvents("PierreBtz")) { + if (ev.getType() == GHEvent.PULL_REQUEST) { + if (ev.getId() == 27449881624L) { + assertThat(ev.getActorLogin(), equalTo("PierreBtz")); + assertThat(ev.getOrganization().getLogin(), equalTo("hub4j")); + assertThat(ev.getRepository().getFullName(), equalTo("hub4j/github-api")); + assertThat(ev.getCreatedAt(), equalTo(GitHubClient.parseDate("2023-03-02T16:37:49Z"))); + assertThat(ev.getType(), equalTo(GHEvent.PULL_REQUEST)); + } + + GHEventPayload.PullRequest pr = ev.getPayload(GHEventPayload.PullRequest.class); + assertThat(pr.getNumber(), is(pr.getPullRequest().getNumber())); } } } /** - * Test issue with no comment. + * Test getEmails. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testIssueWithNoComment() throws IOException { - GHRepository repository = gitHub.getRepository("kohsuke/test"); - GHIssue i = repository.getIssue(4); - List v = i.getComments(); - // System.out.println(v); - assertThat(v, is(empty())); - } - - /** - * Test list commits. - * - * @throws Exception - * the exception - */ - @Test - public void testListCommits() throws Exception { - List sha1 = new ArrayList(); - for (GHCommit c : gitHub.getUser("kohsuke").getRepository("empty-commit").listCommits()) { - sha1.add(c.getSHA1()); - } - assertThat(sha1.get(0), equalTo("fdfad6be4db6f96faea1f153fb447b479a7a9cb7")); - assertThat(sha1.size(), equalTo(1)); + public void testGetEmails() throws IOException { + List emails = gitHub.getMyself().getEmails(); + assertThat(emails.size(), equalTo(2)); + assertThat(emails, contains("bitwiseman@gmail.com", "bitwiseman@users.noreply.github.com")); } /** - * Test list issues. + * Test app. * * @throws IOException * Signals that an I/O exception has occurred. */ + @Ignore("Needs mocking check") @Test - public void testListIssues() throws IOException { - Iterable closedIssues = gitHub.getOrganization("hub4j") - .getRepository("github-api") - .queryIssues() - .state(GHIssueState.CLOSED) - .list(); + public void testApp() throws IOException { + // System.out.println(gitHub.getMyself().getEmails()); - int x = 0; - for (GHIssue issue : closedIssues) { - assertThat(issue, notNullValue()); - x++; + // GHRepository r = gitHub.getOrganization("jenkinsci").createRepository("kktest4", "Kohsuke's test", + // "http://kohsuke.org/", "Everyone", true); + // r.fork(); + + // tryDisablingIssueTrackers(gitHub); + + // tryDisablingWiki(gitHub); + + // GHPullRequest i = gitHub.getOrganization("jenkinsci").getRepository("sandbox").getPullRequest(1); + // for (GHIssueComment c : i.getComments()) + // // System.out.println(c); + // // System.out.println(i); + + // gitHub.getMyself().getRepository("perforce-plugin").setEmailServiceHook("kk@kohsuke.org"); + + // tryRenaming(gitHub); + // tryOrgFork(gitHub); + + // testOrganization(gitHub); + // testPostCommitHook(gitHub); + + // tryTeamCreation(gitHub); + + // t.add(gitHub.getMyself()); + // // System.out.println(t.getMembers()); + // t.remove(gitHub.getMyself()); + // // System.out.println(t.getMembers()); + + // GHRepository r = gitHub.getOrganization("HudsonLabs").createRepository("auto-test", "some description", + // "http://kohsuke.org/", "Plugin Developers", true); + + // r. + // GitHub hub = GitHub.connectAnonymously(); + //// hub.createRepository("test","test repository",null,true); + //// hub.getUserTest("kohsuke").getRepository("test").delete(); + // + // // System.out.println(hub.getUserTest("kohsuke").getRepository("hudson").getCollaborators()); + } + + private void tryDisablingIssueTrackers(GitHub gitHub) throws IOException { + for (GHRepository r : gitHub.getOrganization("jenkinsci").getRepositories().values()) { + if (r.hasIssues()) { + if (r.getOpenIssueCount() == 0) { + // System.out.println("DISABLED " + r.getName()); + r.enableIssueTracker(false); + } else { + // System.out.println("UNTOUCHED " + r.getName()); + } + } } + } - assertThat(x, greaterThan(150)); + private void tryDisablingWiki(GitHub gitHub) throws IOException { + for (GHRepository r : gitHub.getOrganization("jenkinsci").getRepositories().values()) { + if (r.hasWiki()) { + // System.out.println("DISABLED " + r.getName()); + r.enableWiki(false); + } + } + } + + private void tryUpdatingIssueTracker(GitHub gitHub) throws IOException { + GHRepository r = gitHub.getOrganization("jenkinsci").getRepository("lib-task-reactor"); + // System.out.println(r.hasIssues()); + // System.out.println(r.getOpenIssueCount()); + r.enableIssueTracker(false); + } + + private void tryRenaming(GitHub gitHub) throws IOException { + gitHub.getUser("kohsuke").getRepository("test").renameTo("test2"); + } + + private void tryTeamCreation(GitHub gitHub) throws IOException { + GHOrganization o = gitHub.getOrganization("HudsonLabs"); + GHTeam t = o.createTeam("auto team").permission(Permission.PUSH).create(); + t.add(o.getRepository("auto-test")); } /** - * Test member orgs. + * Test org repositories. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testMemberOrgs() throws Exception { - HashSet o = gitHub.getUser("kohsuke").getOrganizations(); - assertThat(o, hasItem(hasProperty("name", equalTo("CloudBees")))); + public void testOrgRepositories() throws IOException { + kohsuke(); + GHOrganization j = gitHub.getOrganization("jenkinsci"); + long start = System.currentTimeMillis(); + Map repos = j.getRepositories(); + long end = System.currentTimeMillis(); + // System.out.printf("%d repositories in %dms\n", repos.size(), end - start); } /** - * Test member pagenation. + * Test organization. * * @throws IOException * Signals that an I/O exception has occurred. */ - @Ignore("Needs mocking check") @Test - public void testMemberPagenation() throws IOException { - Set all = new HashSet(); - for (GHUser u : gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamByName("Core Developers").listMembers()) { - // System.out.println(u.getLogin()); - all.add(u); - } - assertThat(all, is(not(empty()))); + public void testOrganization() throws IOException { + kohsuke(); + GHOrganization j = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHTeam t = j.getTeams().get("Core Developers"); + + assertThat(j.getRepository("jenkins"), notNullValue()); + + // t.add(labs.getRepository("xyz")); } /** - * Test membership. + * Test commit status. * * @throws Exception * the exception */ @Test - public void testMembership() throws Exception { - Set members = gitHub.getOrganization(GITHUB_API_TEST_ORG) - .getRepository("jenkins") - .getCollaboratorNames(); - // System.out.println(members.contains("kohsuke")); + public void testCommitStatus() throws Exception { + GHRepository r = gitHub.getRepository("hub4j/github-api"); + + GHCommitStatus state; + + // state = r.createCommitStatus("ecbfdd7315ef2cf04b2be7f11a072ce0bd00c396", GHCommitState.FAILURE, + // "http://kohsuke.org/", "testing!"); + + List lst = r.listCommitStatuses("ecbfdd7315ef2cf04b2be7f11a072ce0bd00c396").toList(); + state = lst.get(0); + // System.out.println(state); + assertThat(state.getDescription(), equalTo("testing!")); + assertThat(state.getTargetUrl(), equalTo("http://kohsuke.org/")); + assertThat(state.getCreator().getLogin(), equalTo("kohsuke")); } /** - * Test my organizations. + * Test commit short info. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void testMyOrganizations() throws IOException { - Map org = gitHub.getMyOrganizations(); - assertThat(org.containsKey(null), is(false)); - // System.out.println(org); + public void testCommitShortInfo() throws Exception { + GHRepository r = gitHub.getRepository("hub4j/github-api"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f23"); + assertThat("Kohsuke Kawaguchi", equalTo(commit.getCommitShortInfo().getAuthor().getName())); + assertThat("doc", equalTo(commit.getCommitShortInfo().getMessage())); + assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); + assertThat(GHVerification.Reason.UNSIGNED, equalTo(commit.getCommitShortInfo().getVerification().getReason())); + assertThat(commit.getCommitShortInfo().getAuthor().getDate().toInstant().getEpochSecond(), + equalTo(1271650361L)); + assertThat(commit.getCommitShortInfo().getCommitter().getDate().toInstant().getEpochSecond(), + equalTo(1271650361L)); } /** - * Test my organizations contain my teams. + * Test pull request populate. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ + @Ignore("Needs mocking check") @Test - public void testMyOrganizationsContainMyTeams() throws IOException { - Map> teams = gitHub.getMyTeams(); - Map myOrganizations = gitHub.getMyOrganizations(); - // GitHub no longer has default 'owners' team, so there may be organization memberships without a team - // https://help.github.com/articles/about-improved-organization-permissions/ - assertThat(myOrganizations.keySet().containsAll(teams.keySet()), is(true)); + public void testPullRequestPopulate() throws Exception { + GHRepository r = gitHub.getUser("kohsuke").getRepository("github-api"); + GHPullRequest p = r.getPullRequest(17); + GHUser u = p.getUser(); + assertThat(u.getName(), notNullValue()); } /** - * Test my teams should include myself. + * Test check membership. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void testMyTeamsShouldIncludeMyself() throws IOException { - Map> teams = gitHub.getMyTeams(); - for (Entry> teamsPerOrg : teams.entrySet()) { - String organizationName = teamsPerOrg.getKey(); - for (GHTeam team : teamsPerOrg.getValue()) { - String teamName = team.getName(); - assertThat("Team " + teamName + " in organization " + organizationName + " does not contain myself", - shouldBelongToTeam(organizationName, teamName)); - } - } + public void testCheckMembership() throws Exception { + kohsuke(); + GHOrganization j = gitHub.getOrganization("jenkinsci"); + GHUser kohsuke = gitHub.getUser("kohsuke"); + GHUser b = gitHub.getUser("b"); + + assertThat(j.hasMember(kohsuke), is(true)); + assertThat(j.hasMember(b), is(false)); + + assertThat(j.hasPublicMember(kohsuke), is(true)); + assertThat(j.hasPublicMember(b), is(false)); } /** - * Test org fork. + * Test ref. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testOrgFork() throws Exception { - cleanupRepository(GITHUB_API_TEST_ORG + "/rubywm"); - gitHub.getRepository("kohsuke/rubywm").forkTo(gitHub.getOrganization(GITHUB_API_TEST_ORG)); + public void testRef() throws IOException { + GHRef mainRef = gitHub.getRepository("jenkinsci/jenkins").getRef("heads/master"); + assertThat(mainRef.getUrl().toString(), + equalTo(mockGitHub.apiServer().baseUrl() + "/repos/jenkinsci/jenkins/git/refs/heads/master")); } /** - * Test org repositories. + * Directory listing. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testOrgRepositories() throws IOException { - kohsuke(); - GHOrganization j = gitHub.getOrganization("jenkinsci"); - long start = System.currentTimeMillis(); - Map repos = j.getRepositories(); - long end = System.currentTimeMillis(); - // System.out.printf("%d repositories in %dms\n", repos.size(), end - start); + public void directoryListing() throws IOException { + List children = gitHub.getRepository("jenkinsci/jenkins").getDirectoryContent("core"); + for (GHContent c : children) { + // System.out.println(c.getName()); + if (c.isDirectory()) { + for (GHContent d : c.listDirectoryContent()) { + // System.out.println(" " + d.getName()); + } + } + } } /** - * Test org team by name. + * Test add deploy key. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testOrgTeamByName() throws Exception { - kohsuke(); - GHTeam e = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamByName("Core Developers"); - assertThat(e, notNullValue()); + public void testAddDeployKey() throws IOException { + GHRepository myRepository = getTestRepository(); + final GHDeployKey newDeployKey = myRepository.addDeployKey("test", + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIATWwMLytklB44O66isWRKOB3Qd7Ysc7q7EyWTmT0bG9 test@example.com"); + try { + assertThat(newDeployKey.getId(), notNullValue()); + + GHDeployKey k = Iterables.find(myRepository.getDeployKeys(), new Predicate() { + public boolean apply(GHDeployKey deployKey) { + return newDeployKey.getId() == deployKey.getId() && !deployKey.isRead_only(); + } + }); + assertThat(k, notNullValue()); + } finally { + newDeployKey.delete(); + } } /** - * Test org team by slug. + * Test add deploy key read-only. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testOrgTeamBySlug() throws Exception { - kohsuke(); - GHTeam e = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug("core-developers"); - assertThat(e, notNullValue()); + public void testAddDeployKeyAsReadOnly() throws IOException { + GHRepository myRepository = getTestRepository(); + final GHDeployKey newDeployKey = myRepository.addDeployKey("test", + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIATWwMLytklB44O66isWRKOB3Qd7Ysc7q7EyWTmT0bG9 test@example.com", + true); + try { + assertThat(newDeployKey.getId(), notNullValue()); + + GHDeployKey k = Iterables.find(myRepository.getDeployKeys(), new Predicate() { + public boolean apply(GHDeployKey deployKey) { + return newDeployKey.getId() == deployKey.getId() && deployKey.isRead_only(); + } + }); + assertThat(k, notNullValue()); + } finally { + newDeployKey.delete(); + } } /** - * Test org teams. + * Test commit status context. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ + @Ignore("Needs mocking check") @Test - public void testOrgTeams() throws Exception { - kohsuke(); - int sz = 0; - for (GHTeam t : gitHub.getOrganization(GITHUB_API_TEST_ORG).listTeams()) { - assertThat(t.getName(), notNullValue()); - sz++; - } - assertThat(sz, lessThan(100)); + public void testCommitStatusContext() throws IOException { + GHRepository myRepository = getTestRepository(); + GHRef mainRef = myRepository.getRef("heads/main"); + GHCommitStatus commitStatus = myRepository.createCommitStatus(mainRef.getObject() + .getSha(), GHCommitState.SUCCESS, "http://www.example.com", "test", "test/context"); + assertThat(commitStatus.getContext(), equalTo("test/context")); + } /** - * Test organization. + * Test member pagenation. * * @throws IOException * Signals that an I/O exception has occurred. */ + @Ignore("Needs mocking check") @Test - public void testOrganization() throws IOException { - kohsuke(); - GHOrganization j = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHTeam t = j.getTeams().get("Core Developers"); - - assertThat(j.getRepository("jenkins"), notNullValue()); - - // t.add(labs.getRepository("xyz")); + public void testMemberPagenation() throws IOException { + Set all = new HashSet(); + for (GHUser u : gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamByName("Core Developers").listMembers()) { + // System.out.println(u.getLogin()); + all.add(u); + } + assertThat(all, is(not(empty()))); } /** - * Test public keys. + * Test commit search. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ - @Ignore("Needs mocking check") @Test - public void testPublicKeys() throws Exception { - List keys = gitHub.getMyself().getPublicKeys(); - assertThat(keys, is(not(empty()))); + public void testCommitSearch() throws IOException { + PagedSearchIterable r = gitHub.searchCommits() + .org("github-api") + .repo("github-api") + .author("kohsuke") + .sort(GHCommitSearchBuilder.Sort.COMMITTER_DATE) + .list(); + assertThat(r.getTotalCount(), greaterThan(0)); + + GHCommit firstCommit = r.iterator().next(); + assertThat(firstCommit.listFiles().toList(), is(not(empty()))); } /** - * Test pull request populate. + * Test issue search. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ - @Ignore("Needs mocking check") @Test - public void testPullRequestPopulate() throws Exception { - GHRepository r = gitHub.getUser("kohsuke").getRepository("github-api"); - GHPullRequest p = r.getPullRequest(17); - GHUser u = p.getUser(); - assertThat(u.getName(), notNullValue()); + public void testIssueSearch() throws IOException { + PagedSearchIterable r = gitHub.searchIssues() + .mentions("kohsuke") + .isOpen() + .sort(GHIssueSearchBuilder.Sort.UPDATED) + .list(); + assertThat(r.getTotalCount(), greaterThan(0)); + for (GHIssue issue : r) { + assertThat(issue.getTitle(), notNullValue()); + PagedIterable comments = issue.listComments(); + for (GHIssueComment comment : comments) { + assertThat(comment, notNullValue()); + } + } } /** * Test searching for pull requests. * - * @throws Exception + * @throws IOException * the exception */ @Test @@ -1195,114 +1435,26 @@ public void testPullRequestSearch() throws Exception { .commit(); GHPullRequest newPR = repository .createPullRequest("New PR", headBranch.getRef(), "refs/heads/main", "Hello, merged PR"); - newPR.setLabels("test"); - Thread.sleep(1000); - - List pullRequests = gitHub.searchPullRequests() - .repo(repository) - .createdByMe() - .isOpen() - .label("test") - .list() - .toList(); - assertThat(pullRequests.size(), is(1)); - assertThat(pullRequests.get(0).getNumber(), is(newPR.getNumber())); - - int totalCount = gitHub.searchPullRequests() - .repo(repository) - .author(repository.getOwner()) - .isMerged() - .list() - .getTotalCount(); - assertThat(totalCount, is(0)); - } - - /** - * Test query issues. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testQueryIssues() throws IOException { - final GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("testQueryIssues"); - List openBugIssues = repo.queryIssues() - .milestone("1") - .creator(gitHub.getMyself().getLogin()) - .state(GHIssueState.OPEN) - .label("bug") - .pageSize(10) - .list() - .toList(); - GHIssue issueWithMilestone = openBugIssues.get(0); - assertThat(openBugIssues, is(not(empty()))); - assertThat(openBugIssues, hasSize(1)); - assertThat(issueWithMilestone.getTitle(), is("Issue with milestone")); - assertThat(issueWithMilestone.getAssignee().getLogin(), is("bloslo")); - assertThat(issueWithMilestone.getBody(), containsString("@bloslo")); - - List openIssuesWithAssignee = repo.queryIssues() - .assignee(gitHub.getMyself().getLogin()) - .state(GHIssueState.OPEN) - .list() - .toList(); - GHIssue issueWithAssignee = openIssuesWithAssignee.get(0); - assertThat(openIssuesWithAssignee, is(not(empty()))); - assertThat(openIssuesWithAssignee, hasSize(1)); - assertThat(issueWithAssignee.getLabels(), hasSize(2)); - assertThat(issueWithAssignee.getMilestone(), is(notNullValue())); - - List allIssuesSince = repo.queryIssues() - .mentioned(gitHub.getMyself().getLogin()) - .state(GHIssueState.ALL) - .since(1632411646L) - .sort(GHIssueQueryBuilder.Sort.COMMENTS) - .direction(GHDirection.ASC) - .list() - .toList(); - GHIssue issueSince = allIssuesSince.get(3); - assertThat(allIssuesSince, is(not(empty()))); - assertThat(allIssuesSince, hasSize(4)); - assertThat(issueSince.getBody(), is("Test closed issue @bloslo")); - assertThat(issueSince.getState(), is(GHIssueState.CLOSED)); - - List allIssuesWithLabels = repo.queryIssues() - .label("bug") - .label("test-label") - .state(GHIssueState.ALL) - .list() - .toList(); - GHIssue issueWithLabel = allIssuesWithLabels.get(0); - assertThat(allIssuesWithLabels, is(not(empty()))); - assertThat(allIssuesWithLabels, hasSize(5)); - assertThat(issueWithLabel.getComments(), hasSize(2)); - assertThat(issueWithLabel.getTitle(), is("Issue with comments")); - - List issuesWithLabelNull = repo.queryIssues().label(null).list().toList(); - GHIssue issueWithLabelNull = issuesWithLabelNull.get(2); - assertThat(issuesWithLabelNull, is(not(empty()))); - assertThat(issuesWithLabelNull, hasSize(6)); - assertThat(issueWithLabelNull.getTitle(), is("Closed issue")); - assertThat(issueWithLabelNull.getBody(), is("Test closed issue @bloslo")); - assertThat(issueWithLabelNull.getState(), is(GHIssueState.OPEN)); - - List issuesWithLabelEmptyString = repo.queryIssues().label("").state(GHIssueState.ALL).list().toList(); - GHIssue issueWithLabelEmptyString = issuesWithLabelEmptyString.get(0); - assertThat(issuesWithLabelEmptyString, is(not(empty()))); - assertThat(issuesWithLabelEmptyString, hasSize(8)); - assertThat(issueWithLabelEmptyString.getTitle(), is("Closed issue")); - assertThat(issueWithLabelEmptyString.getBody(), is("Test closed issue @bloslo")); - } + newPR.setLabels("test"); + Thread.sleep(1000); - /** - * Test rate limit. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testRateLimit() throws IOException { - assertThat(gitHub.getRateLimit(), notNullValue()); + List pullRequests = gitHub.searchPullRequests() + .repo(repository) + .createdByMe() + .isOpen() + .label("test") + .list() + .toList(); + assertThat(pullRequests.size(), is(1)); + assertThat(pullRequests.get(0).getNumber(), is(newPR.getNumber())); + + int totalCount = gitHub.searchPullRequests() + .repo(repository) + .author(repository.getOwner()) + .isMerged() + .list() + .getTotalCount(); + assertThat(totalCount, is(0)); } /** @@ -1319,67 +1471,52 @@ public void testReadme() throws IOException { } /** - * Test ref. + * Test trees. * * @throws IOException * Signals that an I/O exception has occurred. */ + @Ignore("Needs mocking check") @Test - public void testRef() throws IOException { - GHRef mainRef = gitHub.getRepository("jenkinsci/jenkins").getRef("heads/master"); - assertThat(mainRef.getUrl().toString(), - equalTo(mockGitHub.apiServer().baseUrl() + "/repos/jenkinsci/jenkins/git/refs/heads/master")); + public void testTrees() throws IOException { + GHTree mainTree = gitHub.getRepository("hub4j/github-api").getTree("main"); + boolean foundReadme = false; + for (GHTreeEntry e : mainTree.getTree()) { + if ("readme".equalsIgnoreCase(e.getPath().replaceAll("\\.md", ""))) { + foundReadme = true; + break; + } + } + assertThat(foundReadme, is(true)); } /** - * Test repo CRUD. + * Test trees recursive. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testRepoCRUD() throws Exception { - String targetName = "github-api-test-rename2"; - - cleanupUserRepository("github-api-test-rename"); - cleanupUserRepository(targetName); - - GHRepository r = gitHub.createRepository("github-api-test-rename") - .description("a test repository") - .homepage("http://github-api.kohsuke.org/") - .private_(false) - .create(); - - assertThat(r.hasIssues(), is(true)); - assertThat(r.hasWiki(), is(true)); - assertThat(r.hasDownloads(), is(true)); - assertThat(r.hasProjects(), is(true)); - - r.enableIssueTracker(false); - r.enableDownloads(false); - r.enableWiki(false); - r.enableProjects(false); - - r.renameTo(targetName); - - // local instance remains unchanged - assertThat(r.getName(), equalTo("github-api-test-rename")); - assertThat(r.hasIssues(), is(true)); - assertThat(r.hasWiki(), is(true)); - assertThat(r.hasDownloads(), is(true)); - assertThat(r.hasProjects(), is(true)); - - r = gitHub.getMyself().getRepository(targetName); - - // values are updated - assertThat(r.hasIssues(), is(false)); - assertThat(r.hasWiki(), is(false)); - assertThat(r.hasDownloads(), is(false)); - assertThat(r.getName(), equalTo(targetName)); - - assertThat(r.hasProjects(), is(false)); + public void testTreesRecursive() throws IOException { + GHTree mainTree = gitHub.getRepository("hub4j/github-api").getTreeRecursive("main", 1); + boolean foundThisFile = false; + for (GHTreeEntry e : mainTree.getTree()) { + if (e.getPath().endsWith(AppTest.class.getSimpleName() + ".java")) { + foundThisFile = true; + assertThat(e.getPath(), equalTo("src/test/java/org/kohsuke/github/AppTest.java")); + assertThat(e.getSha(), equalTo("baad7a7c4cf409f610a0e8c7eba17664eb655c44")); + assertThat(e.getMode(), equalTo("100755")); + assertThat(e.getSize(), greaterThan(30000L)); + assertThat(e.getUrl().toString(), + containsString("/repos/hub4j/github-api/git/blobs/baad7a7c4cf409f610a0e8c7eba17664eb655c44")); + GHBlob blob = e.asBlob(); + assertThat(e.asBlob().getUrl().toString(), + containsString("/repos/hub4j/github-api/git/blobs/baad7a7c4cf409f610a0e8c7eba17664eb655c44")); + break; + } - r.delete(); + } + assertThat(foundThisFile, is(true)); } /** @@ -1498,69 +1635,20 @@ public void testRepoLabel() throws IOException { } /** - * Test repo permissions. - * - * @throws Exception - * the exception - */ - @Ignore("Needs mocking check") - @Test - public void testRepoPermissions() throws Exception { - kohsuke(); - - GHRepository r = gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("github-api"); - assertThat(r.hasPullAccess(), is(true)); - - r = gitHub.getOrganization("github").getRepository("hub"); - assertThat(r.hasAdminAccess(), is(false)); - } - - /** - * Test repository with auto initialization CRUD. + * Cleanup label. * - * @throws Exception - * the exception + * @param name + * the name */ - @Test - public void testRepositoryWithAutoInitializationCRUD() throws Exception { - String name = "github-api-test-autoinit"; - cleanupUserRepository(name); - GHRepository r = gitHub.createRepository(name) - .description("a test repository for auto init") - .homepage("http://github-api.kohsuke.org/") - .autoInit(true) - .create(); + void cleanupLabel(String name) { if (mockGitHub.isUseProxy()) { - Thread.sleep(3000); - } - assertThat(r.getReadme(), notNullValue()); - - r.delete(); - } - - /** - * Test should fetch team from organization. - * - * @throws Exception - * the exception - */ - @Test - public void testShouldFetchTeamFromOrganization() throws Exception { - GHOrganization organization = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHTeam teamByName = organization.getTeams().get("Core Developers"); - - GHTeam teamById = organization.getTeam(teamByName.getId()); - assertThat(teamById, notNullValue()); - - assertThat(teamById.getId(), equalTo(teamByName.getId())); - assertThat(teamById.getDescription(), equalTo(teamByName.getDescription())); - - GHTeam teamById2 = organization.getTeam(teamByName.getId()); - assertThat(teamById2, notNullValue()); - - assertThat(teamById2.getId(), equalTo(teamByName.getId())); - assertThat(teamById2.getDescription(), equalTo(teamByName.getDescription())); + try { + GHLabel t = getNonRecordingGitHub().getRepository("hub4j-test-org/test-labels").getLabel(name); + t.delete(); + } catch (IOException e) { + } + } } /** @@ -1586,246 +1674,161 @@ public void testSubscribers() throws IOException { } /** - * Test trees. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Ignore("Needs mocking check") - @Test - public void testTrees() throws IOException { - GHTree mainTree = gitHub.getRepository("hub4j/github-api").getTree("main"); - boolean foundReadme = false; - for (GHTreeEntry e : mainTree.getTree()) { - if ("readme".equalsIgnoreCase(e.getPath().replaceAll("\\.md", ""))) { - foundReadme = true; - break; - } - } - assertThat(foundReadme, is(true)); - } - - /** - * Test trees recursive. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testTreesRecursive() throws IOException { - GHTree mainTree = gitHub.getRepository("hub4j/github-api").getTreeRecursive("main", 1); - boolean foundThisFile = false; - for (GHTreeEntry e : mainTree.getTree()) { - if (e.getPath().endsWith(AppTest.class.getSimpleName() + ".java")) { - foundThisFile = true; - assertThat(e.getPath(), equalTo("src/test/java/org/kohsuke/github/AppTest.java")); - assertThat(e.getSha(), equalTo("baad7a7c4cf409f610a0e8c7eba17664eb655c44")); - assertThat(e.getMode(), equalTo("100755")); - assertThat(e.getSize(), greaterThan(30000L)); - assertThat(e.getUrl().toString(), - containsString("/repos/hub4j/github-api/git/blobs/baad7a7c4cf409f610a0e8c7eba17664eb655c44")); - GHBlob blob = e.asBlob(); - assertThat(e.asBlob().getUrl().toString(), - containsString("/repos/hub4j/github-api/git/blobs/baad7a7c4cf409f610a0e8c7eba17664eb655c44")); - break; - } - - } - assertThat(foundThisFile, is(true)); - } - - /** - * Test user public event api. - * - * @throws Exception - * the exception - */ - @Test - public void testUserPublicEventApi() throws Exception { - for (GHEventInfo ev : gitHub.getUserPublicEvents("PierreBtz")) { - if (ev.getType() == GHEvent.PULL_REQUEST) { - if (ev.getId() == 27449881624L) { - assertThat(ev.getActorLogin(), equalTo("PierreBtz")); - assertThat(ev.getOrganization().getLogin(), equalTo("hub4j")); - assertThat(ev.getRepository().getFullName(), equalTo("hub4j/github-api")); - assertThat(ev.getCreatedAt(), equalTo(GitHubClient.parseInstant("2023-03-02T16:37:49Z"))); - assertThat(ev.getType(), equalTo(GHEvent.PULL_REQUEST)); - } - - GHEventPayload.PullRequest pr = ev.getPayload(GHEventPayload.PullRequest.class); - assertThat(pr.getNumber(), is(pr.getPullRequest().getNumber())); - } - if (ev.getType() == GHEvent.PULL_REQUEST_REVIEW) { - if (ev.getId() == 27468578706L) { - GHEventPayload.PullRequestReview prr = ev.getPayload(GHEventPayload.PullRequestReview.class); - assertThat(prr.getReview().getSubmittedAt(), - equalTo(GitHubClient.parseInstant("2023-03-03T10:51:48Z"))); - assertThat(prr.getReview().getCreatedAt(), equalTo(prr.getReview().getSubmittedAt())); - } - } - } - } - - /** - * Test user public organizations when there are none. + * Notifications. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void testUserPublicOrganizationsWhenThereAreNone() throws IOException { - // bitwiseman had no public org memberships at the time Wiremock recorded the GitHub API responses - GHUser user = new GHUser(); - user.login = "bitwiseman"; + public void notifications() throws Exception { + boolean found = false; + for (GHThread t : gitHub.listNotifications().nonBlocking(true).read(true)) { + if (!found) { + found = true; + // both read and unread are included + assertThat(t.getTitle(), is("Create a Jenkinsfile for Librecores CI in mor1kx")); + assertThat(t.getLastReadAt(), notNullValue()); + assertThat(t.isRead(), equalTo(true)); - Map orgs = gitHub.getUserPublicOrganizations(user); - assertThat(orgs.size(), equalTo(0)); + t.markAsRead(); // test this by calling it once on old notfication + } + assertThat(t.getReason(), oneOf("subscribed", "mention", "review_requested", "comment")); + assertThat(t.getTitle(), notNullValue()); + assertThat(t.getLastCommentUrl(), notNullValue()); + assertThat(t.getRepository(), notNullValue()); + assertThat(t.getUpdatedAt(), notNullValue()); + assertThat(t.getType(), oneOf("Issue", "PullRequest")); + + // both thread an unread are included + // assertThat(t.getLastReadAt(), notNullValue()); + // assertThat(t.isRead(), equalTo(true)); + + // Doesn't exist on threads but is part of GHObject. :( + assertThat(t.getCreatedAt(), nullValue()); + + } + assertThat(found, is(true)); + gitHub.listNotifications().markAsRead(); } /** - * Test user public organizations when there are some. + * Check to string. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ + @Ignore("Needs mocking check") @Test - public void testUserPublicOrganizationsWhenThereAreSome() throws IOException { - // kohsuke had some public org memberships at the time Wiremock recorded the GitHub API responses - GHUser user = new GHUser(); - user.login = "kohsuke"; - - Map orgs = gitHub.getUserPublicOrganizations(user); - assertThat(orgs.size(), greaterThan(0)); + public void checkToString() throws Exception { + // Just basic code coverage to make sure toString() doesn't blow up + GHUser u = gitHub.getUser("rails"); + // System.out.println(u); + GHRepository r = u.getRepository("rails"); + // System.out.println(r); + // System.out.println(r.getIssue(1)); } /** - * Try hook. + * Reactions. * * @throws Exception * the exception */ @Test - public void tryHook() throws Exception { - final GHOrganization o = gitHub.getOrganization(GITHUB_API_TEST_ORG); - final GHRepository r = o.getRepository("github-api"); - try { - GHHook hook = r.createWebHook(new URL("http://www.google.com/")); - assertThat(hook.getName(), equalTo("web")); - assertThat(hook.getEvents().size(), equalTo(1)); - assertThat(hook.getEvents(), contains(GHEvent.PUSH)); - assertThat(hook.getConfig().size(), equalTo(3)); - assertThat(hook.isActive(), equalTo(true)); + public void reactions() throws Exception { + GHIssue i = gitHub.getRepository("hub4j/github-api").getIssue(311); - GHHook hook2 = r.getHook((int) hook.getId()); - assertThat(hook2.getName(), equalTo("web")); - assertThat(hook2.getEvents().size(), equalTo(1)); - assertThat(hook2.getEvents(), contains(GHEvent.PUSH)); - assertThat(hook2.getConfig().size(), equalTo(3)); - assertThat(hook2.isActive(), equalTo(true)); - hook2.ping(); - hook2.delete(); - final GHHook finalRepoHook = hook; - GHFileNotFoundException e = Assert.assertThrows(GHFileNotFoundException.class, - () -> r.getHook((int) finalRepoHook.getId())); - assertThat(e.getMessage(), - containsString("repos/hub4j-test-org/github-api/hooks/" + finalRepoHook.getId())); - assertThat(e.getMessage(), containsString("rest/reference/repos#get-a-repository-webhook")); + List l; + // retrieval + l = i.listReactions().toList(); + assertThat(l.size(), equalTo(1)); - hook = r.createWebHook(new URL("http://www.google.com/")); - r.deleteHook((int) hook.getId()); + assertThat(l.get(0).getUser().getLogin(), is("kohsuke")); + assertThat(l.get(0).getContent(), is(ReactionContent.HEART)); - hook = o.createWebHook(new URL("http://www.google.com/")); - assertThat(hook.getName(), equalTo("web")); - assertThat(hook.getEvents().size(), equalTo(1)); - assertThat(hook.getEvents(), contains(GHEvent.PUSH)); - assertThat(hook.getConfig().size(), equalTo(3)); - assertThat(hook.isActive(), equalTo(true)); + // CRUD + GHReaction a; + a = i.createReaction(ReactionContent.HOORAY); + assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(a.getContent(), is(ReactionContent.HOORAY)); + i.deleteReaction(a); - hook2 = o.getHook((int) hook.getId()); - assertThat(hook2.getName(), equalTo("web")); - assertThat(hook2.getEvents().size(), equalTo(1)); - assertThat(hook2.getEvents(), contains(GHEvent.PUSH)); - assertThat(hook2.getConfig().size(), equalTo(3)); - assertThat(hook2.isActive(), equalTo(true)); - hook2.ping(); - hook2.delete(); + l = i.listReactions().toList(); + assertThat(l.size(), equalTo(1)); - final GHHook finalOrgHook = hook; - GHFileNotFoundException e2 = Assert.assertThrows(GHFileNotFoundException.class, - () -> o.getHook((int) finalOrgHook.getId())); - assertThat(e2.getMessage(), containsString("orgs/hub4j-test-org/hooks/" + finalOrgHook.getId())); - assertThat(e2.getMessage(), containsString("rest/reference/orgs#get-an-organization-webhook")); + a = i.createReaction(ReactionContent.PLUS_ONE); + assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(a.getContent(), is(ReactionContent.PLUS_ONE)); - hook = o.createWebHook(new URL("http://www.google.com/")); - o.deleteHook((int) hook.getId()); + a = i.createReaction(ReactionContent.CONFUSED); + assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(a.getContent(), is(ReactionContent.CONFUSED)); - // System.out.println(hook); - } finally { - if (mockGitHub.isUseProxy()) { - GHRepository cleanupRepo = getNonRecordingGitHub().getOrganization(GITHUB_API_TEST_ORG) - .getRepository("github-api"); - for (GHHook h : cleanupRepo.getHooks()) { - h.delete(); - } - } - } - } + a = i.createReaction(ReactionContent.EYES); + assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(a.getContent(), is(ReactionContent.EYES)); - private void cleanupUserRepository(final String name) throws IOException { - if (mockGitHub.isUseProxy()) { - cleanupRepository(getUser(getNonRecordingGitHub()).getLogin() + "/" + name); - } - } + a = i.createReaction(ReactionContent.ROCKET); + assertThat(a.getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(a.getContent(), is(ReactionContent.ROCKET)); - private GHRepository getTestRepository() throws IOException { - return getTempRepository(GITHUB_API_TEST_REPO); - } + l = i.listReactions().toList(); + assertThat(l.size(), equalTo(5)); + assertThat(l.get(0).getUser().getLogin(), is("kohsuke")); + assertThat(l.get(0).getContent(), is(ReactionContent.HEART)); + assertThat(l.get(1).getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(l.get(1).getContent(), is(ReactionContent.PLUS_ONE)); + assertThat(l.get(2).getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(l.get(2).getContent(), is(ReactionContent.CONFUSED)); + assertThat(l.get(3).getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(l.get(3).getContent(), is(ReactionContent.EYES)); + assertThat(l.get(4).getUser().getLogin(), is(gitHub.getMyself().getLogin())); + assertThat(l.get(4).getContent(), is(ReactionContent.ROCKET)); - private boolean shouldBelongToTeam(String organizationName, String teamName) throws IOException { - GHOrganization org = gitHub.getOrganization(organizationName); - assertThat(org, notNullValue()); - GHTeam team = org.getTeamByName(teamName); - assertThat(team, notNullValue()); - return team.hasMember(gitHub.getMyself()); - } + i.deleteReaction(l.get(1)); + i.deleteReaction(l.get(2)); + i.deleteReaction(l.get(3)); + i.deleteReaction(l.get(4)); - private void tryDisablingIssueTrackers(GitHub gitHub) throws IOException { - for (GHRepository r : gitHub.getOrganization("jenkinsci").getRepositories().values()) { - if (r.hasIssues()) { - if (r.getOpenIssueCount() == 0) { - // System.out.println("DISABLED " + r.getName()); - r.enableIssueTracker(false); - } else { - // System.out.println("UNTOUCHED " + r.getName()); - } - } - } + l = i.listReactions().toList(); + assertThat(l.size(), equalTo(1)); } - private void tryDisablingWiki(GitHub gitHub) throws IOException { - for (GHRepository r : gitHub.getOrganization("jenkinsci").getRepositories().values()) { - if (r.hasWiki()) { - // System.out.println("DISABLED " + r.getName()); - r.enableWiki(false); - } + /** + * List org memberships. + * + * @throws Exception + * the exception + */ + @Test + public void listOrgMemberships() throws Exception { + GHMyself me = gitHub.getMyself(); + for (GHMembership m : me.listOrgMemberships()) { + assertThat(m.getUser(), is((GHUser) me)); + assertThat(m.getState(), notNullValue()); + assertThat(m.getRole(), notNullValue()); } } - private void tryRenaming(GitHub gitHub) throws IOException { - gitHub.getUser("kohsuke").getRepository("test").renameTo("test2"); - } + /** + * Blob. + * + * @throws Exception + * the exception + */ + @Test + public void blob() throws Exception { + Assume.assumeFalse(SystemUtils.IS_OS_WINDOWS); - private void tryTeamCreation(GitHub gitHub) throws IOException { - GHOrganization o = gitHub.getOrganization("HudsonLabs"); - GHTeam t = o.createTeam("auto team").permission(Permission.PUSH).create(); - t.add(o.getRepository("auto-test")); - } + GHRepository r = gitHub.getRepository("hub4j/github-api"); + String sha1 = "a12243f2fc5b8c2ba47dd677d0b0c7583539584d"; - private void tryUpdatingIssueTracker(GitHub gitHub) throws IOException { - GHRepository r = gitHub.getOrganization("jenkinsci").getRepository("lib-task-reactor"); - // System.out.println(r.hasIssues()); - // System.out.println(r.getOpenIssueCount()); - r.enableIssueTracker(false); + verifyBlobContent(r.readBlob(sha1)); + + GHBlob blob = r.getBlob(sha1); + verifyBlobContent(blob.read()); + assertThat(blob.getSha(), is("a12243f2fc5b8c2ba47dd677d0b0c7583539584d")); + assertThat(blob.getSize(), is(1104L)); } private void verifyBlobContent(InputStream is) throws Exception { @@ -1834,21 +1837,4 @@ private void verifyBlobContent(InputStream is) throws Exception { assertThat(content, containsString("FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR")); assertThat(content.length(), is(1104)); } - - /** - * Cleanup label. - * - * @param name - * the name - */ - void cleanupLabel(String name) { - if (mockGitHub.isUseProxy()) { - try { - GHLabel t = getNonRecordingGitHub().getRepository("hub4j-test-org/test-labels").getLabel(name); - t.delete(); - } catch (IOException e) { - - } - } - } } diff --git a/src/test/java/org/kohsuke/github/ArchTests.java b/src/test/java/org/kohsuke/github/ArchTests.java index 6c70dcdf82..e21a7ab108 100644 --- a/src/test/java/org/kohsuke/github/ArchTests.java +++ b/src/test/java/org/kohsuke/github/ArchTests.java @@ -1,16 +1,13 @@ package org.kohsuke.github; import com.tngtech.archunit.base.DescribedPredicate; -import com.tngtech.archunit.base.HasDescription; import com.tngtech.archunit.core.domain.*; import com.tngtech.archunit.core.domain.properties.HasName; import com.tngtech.archunit.core.domain.properties.HasOwner; -import com.tngtech.archunit.core.domain.properties.HasSourceCodeLocation; import com.tngtech.archunit.core.importer.ClassFileImporter; import com.tngtech.archunit.core.importer.ImportOption; import com.tngtech.archunit.lang.ArchCondition; import com.tngtech.archunit.lang.ArchRule; -import com.tngtech.archunit.lang.conditions.ArchConditions; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; @@ -18,9 +15,6 @@ import org.apache.commons.lang3.builder.ToStringStyle; import org.junit.BeforeClass; import org.junit.Test; -import org.kohsuke.github.GHDiscussion.Creator; -import org.kohsuke.github.GHPullRequestCommitDetail.Commit; -import org.kohsuke.github.GHPullRequestCommitDetail.CommitPointer; import java.io.Closeable; import java.io.InputStream; @@ -32,25 +26,15 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; -import static com.tngtech.archunit.base.DescribedPredicate.not; -import static com.tngtech.archunit.base.DescribedPredicate.or; import static com.tngtech.archunit.core.domain.JavaCall.Predicates.target; -import static com.tngtech.archunit.core.domain.JavaClass.Predicates.assignableTo; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAPackage; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.type; -import static com.tngtech.archunit.core.domain.JavaMember.Predicates.declaredIn; -import static com.tngtech.archunit.core.domain.JavaModifier.STATIC; -import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameContaining; import static com.tngtech.archunit.core.domain.properties.HasOwner.Predicates.With.owner; import static com.tngtech.archunit.core.domain.properties.HasParameterTypes.Predicates.rawParameterTypes; import static com.tngtech.archunit.lang.conditions.ArchConditions.*; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; -import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.fields; -import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; -import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noFields; -import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noMethods; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThan; @@ -58,49 +42,25 @@ /** * The Class ArchTests. */ -@SuppressWarnings({ "LocalVariableNamingConvention", "TestMethodWithoutAssertion", "UnqualifiedStaticUsage", - "unchecked", "MethodMayBeStatic", "FieldNamingConvention", "StaticCollection" }) public class ArchTests { - private static final class EnumConstantFieldPredicate extends DescribedPredicate { - private EnumConstantFieldPredicate() { - super("are not enum constants"); - } - - @Override - public boolean test(JavaField javaField) { - JavaClass owner = javaField.getOwner(); - return owner.isEnum() && javaField.getRawType().isAssignableTo(owner.reflect()); - } - } - - private static class UnlessPredicate extends DescribedPredicate { - private final DescribedPredicate current; - private final DescribedPredicate other; - - UnlessPredicate(DescribedPredicate current, DescribedPredicate other) { - super(current.getDescription() + " unless " + other.getDescription()); - this.current = checkNotNull(current); - this.other = checkNotNull(other); - } - - @Override - public boolean test(T input) { - return current.test(input) && !other.test(input); - } - } - - private static final JavaClasses apacheCommons = new ClassFileImporter().importPackages("org.apache.commons.lang3"); - private static final JavaClasses classFiles = new ClassFileImporter() .withImportOption(new ImportOption.DoNotIncludeTests()) .importPackages("org.kohsuke.github"); + private static final JavaClasses apacheCommons = new ClassFileImporter().importPackages("org.apache.commons.lang3"); + private static final JavaClasses testClassFiles = new ClassFileImporter() .withImportOption(new ImportOption.OnlyIncludeTests()) .withImportOption(new ImportOption.DoNotIncludeJars()) .importPackages("org.kohsuke.github"); + /** + * Default constructor. + */ + public ArchTests() { + } + /** * Before class. */ @@ -110,26 +70,69 @@ public static void beforeClass() { } /** - * Have names containing unless. - * - * @param - * the generic type - * @param infix - * the infix - * @param unlessPredicates - * the unless predicates - * @return the arch condition + * Test require use of assert that. */ - public static ArchCondition haveNamesContainingUnless( - final String infix, - final DescribedPredicate... unlessPredicates) { - DescribedPredicate restrictedNameContaining = nameContaining(infix); + @Test + public void testRequireUseOfAssertThat() { - if (unlessPredicates.length > 0) { - final DescribedPredicate allowed = or(unlessPredicates); - restrictedNameContaining = unless(nameContaining(infix), allowed); - } - return have(restrictedNameContaining); + final String reason = "This project uses `assertThat(...)` or `assertThrows(...)` instead of other `assert*()` methods."; + + final DescribedPredicate assertMethodOtherThanAssertThat = nameContaining("assert") + .and(DescribedPredicate.not(name("assertThat")).and(DescribedPredicate.not(name("assertThrows")))); + + final ArchRule onlyAssertThatRule = classes() + .should(not(callMethodWhere(target(assertMethodOtherThanAssertThat)))) + .because(reason); + + onlyAssertThatRule.check(testClassFiles); + } + + /** + * Test require use of only specific apache commons. + */ + @Test + public void testRequireUseOfOnlySpecificApacheCommons() { + + final ArchRule onlyApprovedApacheCommonsMethods = classes() + .should(notCallMethodsInPackageUnless("org.apache.commons..", + // unless it is one of these methods + targetMethodIs(StringUtils.class, "capitalize", String.class), + targetMethodIs(StringUtils.class, "defaultString", String.class, String.class), + targetMethodIs(StringUtils.class, "equals", CharSequence.class, CharSequence.class), + targetMethodIs(StringUtils.class, "isBlank", CharSequence.class), + targetMethodIs(StringUtils.class, "isEmpty", CharSequence.class), + targetMethodIs(StringUtils.class, "join", Iterable.class, String.class), + targetMethodIs(StringUtils.class, + "prependIfMissing", + String.class, + CharSequence.class, + CharSequence[].class), + targetMethodIs(ToStringBuilder.class, "toString"), + targetMethodIs(ToStringBuilder.class, "append", String.class, Object.class), + targetMethodIs(ToStringBuilder.class, "append", String.class, long.class), + targetMethodIs(ToStringBuilder.class, "append", String.class, int.class), + targetMethodIs(ToStringBuilder.class, "append", String.class, boolean.class), + targetMethodIs(ToStringBuilder.class, "isEmpty"), + targetMethodIs(ToStringBuilder.class, "equals"), + targetMethodIs(ToStringBuilder.class, "capitalize"), + targetMethodIs(ToStringStyle.class, + "append", + StringBuffer.class, + String.class, + Object.class, + Boolean.class), + targetMethodIs(ReflectionToStringBuilder.class, "accept", Field.class), + targetMethodIs(IOUtils.class, "closeQuietly", InputStream.class), + targetMethodIs(IOUtils.class, "closeQuietly", Closeable.class), + targetMethodIs(IOUtils.class, "copyLarge", InputStream.class, OutputStream.class), + targetMethodIs(IOUtils.class, "toString", InputStream.class, Charset.class), + targetMethodIs(IOUtils.class, "toString", Reader.class), + targetMethodIs(IOUtils.class, "toByteArray", InputStream.class), + targetMethodIs(IOUtils.class, "write", byte[].class, OutputStream.class))) + .because( + "Commons methods must be manually verified to be compatible with commons-io:2.4 or earlier and commons-lang3:3.9 or earlier."); + + onlyApprovedApacheCommonsMethods.check(classFiles); } /** @@ -153,7 +156,7 @@ public static ArchCondition notCallMethodsInPackageUnless(final Strin } restrictedPackageCalls = unless(restrictedPackageCalls, allowed); } - return ArchConditions.not(callMethodWhere(restrictedPackageCalls)); + return not(callMethodWhere(restrictedPackageCalls)); } /** @@ -197,145 +200,19 @@ public static DescribedPredicate unless(DescribedPredicate fir return new UnlessPredicate(first, second); } - private DescribedPredicate and; - - /** - * Default constructor. - */ - public ArchTests() { - } - - /** - * Test naming conventions - */ - @Test - public void testRequireFollowingNamingConvention() { - final String reason = "This project follows standard java naming conventions and does not allow the use of underscores in names."; - - final ArchRule constantFieldsShouldFollowConvention = fields().that() - .areStatic() - .and() - .areFinal() - .should(haveNameMatching("[a-zA-Z$][a-zA-Z0-9$_]*")) - .because(reason); - - final ArchRule enumsShouldFollowConvention = fields().that(enumConstants()) - .and(not(declaredIn(GHCompare.Status.class))) - .should(haveNameMatching("[A-Z][A-Z0-9_]*")) - .because("This project follows standard java naming conventions for enums."); - - var notStaticFinalFields = DescribedPredicate.not(modifier(STATIC).and(modifier(STATIC))); - var notEnumOrStaticFinalFields = DescribedPredicate.and(not(enumConstants()), notStaticFinalFields); - - final ArchRule instanceFieldsShouldNotBePublic = fields().that(notEnumOrStaticFinalFields) - .should(notHaveModifier(JavaModifier.PUBLIC)) - .because("This project does not allow public instance fields."); - - final ArchRule instanceFieldsShouldFollowConvention = noFields().that(notEnumOrStaticFinalFields) - .should(haveNamesContainingUnless("_")) - .because("This project follows standard java naming conventions for fields."); - - @SuppressWarnings("AccessStaticViaInstance") - final ArchRule methodsNotFollowingConvention = noMethods().that() - .arePublic() - .should(haveNamesContainingUnless("_", - // currently failing method names - // TODO: 2025-03-28 Fix & remove these - declaredIn(assignableTo(PagedIterable.class)).and(name("_iterator")), - declaredIn(GHCompare.class).and(name("getAdded_by")), - declaredIn(GHDeployKey.class).and(name("getAdded_by")), - declaredIn(GHDeployKey.class).and(name("isRead_only")), - declaredIn(assignableTo(GHRepositoryBuilder.class)).and(name("private_")), - declaredIn(Creator.class).and(name("private_")), - declaredIn(GHGistBuilder.class).and(name("public_")), - declaredIn(Commit.class).and(name("getComment_count")), - declaredIn(CommitPointer.class).and(name("getHtml_url")), - declaredIn(GHRelease.class).and(name("getPublished_at")))) - .because(reason); - - final ArchRule classesNotFollowingConvention = noClasses().should(haveNamesContainingUnless("_")) - .because(reason); - - enumsShouldFollowConvention.check(classFiles); - constantFieldsShouldFollowConvention.check(classFiles); - instanceFieldsShouldNotBePublic.check(classFiles); - instanceFieldsShouldFollowConvention.check(classFiles); - methodsNotFollowingConvention.check(classFiles); - classesNotFollowingConvention.check(classFiles); - } - - /** - * Test require use of assert that. - */ - @Test - public void testRequireUseOfAssertThat() { - - final String reason = "This project uses `assertThat(...)` or `assertThrows(...)` instead of other `assert*()` methods."; - - final DescribedPredicate assertMethodOtherThanAssertThat = nameContaining("assert") - .and(not(name("assertThat")).and(not(name("assertThrows")))); - - final ArchRule onlyAssertThatRule = classes() - .should(ArchConditions.not(callMethodWhere(target(assertMethodOtherThanAssertThat)))) - .because(reason); - - onlyAssertThatRule.check(testClassFiles); - } - - /** - * Test require use of only specific apache commons. - */ - @Test - public void testRequireUseOfOnlySpecificApacheCommons() { - - final ArchRule onlyApprovedApacheCommonsMethods = classes() - .should(notCallMethodsInPackageUnless("org.apache.commons..", - // unless it is one of these methods - targetMethodIs(StringUtils.class, "capitalize", String.class), - targetMethodIs(StringUtils.class, "defaultString", String.class, String.class), - targetMethodIs(StringUtils.class, "equals", CharSequence.class, CharSequence.class), - targetMethodIs(StringUtils.class, "isBlank", CharSequence.class), - targetMethodIs(StringUtils.class, "isEmpty", CharSequence.class), - targetMethodIs(StringUtils.class, "join", Iterable.class, String.class), - targetMethodIs(StringUtils.class, - "prependIfMissing", - String.class, - CharSequence.class, - CharSequence[].class), - targetMethodIs(ToStringBuilder.class, "toString"), - targetMethodIs(ToStringBuilder.class, "append", String.class, Object.class), - targetMethodIs(ToStringBuilder.class, "append", String.class, long.class), - targetMethodIs(ToStringBuilder.class, "append", String.class, int.class), - targetMethodIs(ToStringBuilder.class, "append", String.class, boolean.class), - targetMethodIs(ToStringBuilder.class, "isEmpty"), - targetMethodIs(ToStringBuilder.class, "equals"), - targetMethodIs(ToStringBuilder.class, "capitalize"), - targetMethodIs(ToStringStyle.class, - "append", - StringBuffer.class, - String.class, - Object.class, - Boolean.class), - targetMethodIs(ReflectionToStringBuilder.class, "accept", Field.class), - targetMethodIs(IOUtils.class, "closeQuietly", InputStream.class), - targetMethodIs(IOUtils.class, "closeQuietly", Closeable.class), - targetMethodIs(IOUtils.class, "copyLarge", InputStream.class, OutputStream.class), - targetMethodIs(IOUtils.class, "toString", InputStream.class, Charset.class), - targetMethodIs(IOUtils.class, "toString", Reader.class), - targetMethodIs(IOUtils.class, "toByteArray", InputStream.class), - targetMethodIs(IOUtils.class, "write", byte[].class, OutputStream.class))) - .because( - "Commons methods must be manually verified to be compatible with commons-io:2.4 or earlier and commons-lang3:3.9 or earlier."); + private static class UnlessPredicate extends DescribedPredicate { + private final DescribedPredicate current; + private final DescribedPredicate other; - onlyApprovedApacheCommonsMethods.check(classFiles); - } + UnlessPredicate(DescribedPredicate current, DescribedPredicate other) { + super(current.getDescription() + " unless " + other.getDescription()); + this.current = checkNotNull(current); + this.other = checkNotNull(other); + } - /** - * Enum constants. - * - * @return the described predicate - */ - private DescribedPredicate enumConstants() { - return new EnumConstantFieldPredicate(); + @Override + public boolean test(T input) { + return current.test(input) && !other.test(input); + } } } diff --git a/src/test/java/org/kohsuke/github/BridgeMethodTest.java b/src/test/java/org/kohsuke/github/BridgeMethodTest.java index 1960b3073c..a4ccdd5d09 100644 --- a/src/test/java/org/kohsuke/github/BridgeMethodTest.java +++ b/src/test/java/org/kohsuke/github/BridgeMethodTest.java @@ -3,10 +3,9 @@ import org.junit.Assert; import org.junit.Test; +import java.io.IOException; import java.lang.reflect.Method; -import java.time.Instant; import java.util.ArrayList; -import java.util.Date; import java.util.List; import javax.annotation.Nonnull; @@ -29,9 +28,12 @@ public BridgeMethodTest() { /** * Test bridge methods. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testBridgeMethods() { + public void testBridgeMethods() throws IOException { // Some would say this is redundant, given that bridge methods are so thin anyway // In the interest of maintaining binary compatibility, we'll do this anyway for a sampling of methods @@ -40,63 +42,8 @@ public void testBridgeMethods() { // verifyBridgeMethods(new GHCommit(), "getAuthor", GHCommit.GHAuthor.class, GitUser.class); // verifyBridgeMethods(new GHCommit(), "getCommitter", GHCommit.GHAuthor.class, GitUser.class); - String artifactId = System.getProperty("test.projectArtifactId", "default"); - // Only run these tests when building the "bridged" artifact - org.junit.Assume.assumeThat(artifactId, equalTo("github-api-bridged")); + // verifyBridgeMethods(GitHub.class, "getMyself", GHMyself.class, GHUser.class); - verifyBridgeMethods(GHAppInstallation.class, "getSuspendedAt", Date.class, Instant.class); - verifyBridgeMethods(GHAppInstallationToken.class, "getExpiresAt", Date.class, Instant.class); - verifyBridgeMethods(GHArtifact.class, "getExpiresAt", Date.class, Instant.class); - verifyBridgeMethods(GHCheckRun.class, "getStartedAt", Date.class, Instant.class); - verifyBridgeMethods(GHCheckRun.class, "getCompletedAt", Date.class, Instant.class); - verifyBridgeMethods(GHCheckSuite.HeadCommit.class, "getTimestamp", Date.class, Instant.class); - verifyBridgeMethods(GHCommit.class, "getAuthoredDate", Date.class, Instant.class); - verifyBridgeMethods(GHCommit.class, "getCommitDate", Date.class, Instant.class); - verifyBridgeMethods(GHDeployKey.class, "getCreatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHDeployKey.class, "getLastUsedAt", Date.class, Instant.class); - verifyBridgeMethods(GHEventInfo.class, "getCreatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHEventPayload.Push.PushCommit.class, "getTimestamp", Date.class, Instant.class); - verifyBridgeMethods(GHEventPayload.Star.class, "getStarredAt", Date.class, Instant.class); - verifyBridgeMethods(GHExternalGroup.class, "getUpdatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHIssue.class, "getClosedAt", Date.class, Instant.class); - verifyBridgeMethods(GHIssueEvent.class, "getCreatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHMarketplacePendingChange.class, "getEffectiveDate", Date.class, Instant.class); - verifyBridgeMethods(GHMarketplacePurchase.class, "getNextBillingDate", Date.class, Instant.class); - verifyBridgeMethods(GHMarketplacePurchase.class, "getFreeTrialEndsOn", Date.class, Instant.class); - verifyBridgeMethods(GHMarketplacePurchase.class, "getUpdatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHMarketplaceUserPurchase.class, "getNextBillingDate", Date.class, Instant.class); - verifyBridgeMethods(GHMarketplaceUserPurchase.class, "getFreeTrialEndsOn", Date.class, Instant.class); - verifyBridgeMethods(GHMarketplaceUserPurchase.class, "getUpdatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHMilestone.class, "getDueOn", Date.class, Instant.class); - verifyBridgeMethods(GHMilestone.class, "getClosedAt", Date.class, Instant.class); - verifyBridgeMethods(GHObject.class, "getCreatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHObject.class, "getUpdatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHPerson.class, "getCreatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHPerson.class, "getUpdatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHProjectsV2Item.class, "getArchivedAt", Date.class, Instant.class); - verifyBridgeMethods(GHProjectsV2ItemChanges.FromToDate.class, "getFrom", Date.class, Instant.class); - verifyBridgeMethods(GHProjectsV2ItemChanges.FromToDate.class, "getTo", Date.class, Instant.class); - verifyBridgeMethods(GHPullRequest.class, "getMergedAt", Date.class, Instant.class); - verifyBridgeMethods(GHPullRequestReview.class, "getSubmittedAt", Date.class, Instant.class); - verifyBridgeMethods(GHPullRequestReview.class, "getCreatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHRepository.class, "getPushedAt", Date.class, Instant.class); - verifyBridgeMethods(GHRepositoryDiscussion.class, "getAnswerChosenAt", Date.class, Instant.class); - verifyBridgeMethods(GHRepositoryDiscussion.class, "getCreatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHRepositoryDiscussion.class, "getUpdatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHRepositoryTraffic.DailyInfo.class, "getTimestamp", Date.class, Instant.class); - verifyBridgeMethods(GHStargazer.class, "getStarredAt", Date.class, Instant.class); - verifyBridgeMethods(GHSubscription.class, "getCreatedAt", Date.class, Instant.class); - verifyBridgeMethods(GHThread.class, "getLastReadAt", Date.class, Instant.class); - verifyBridgeMethods(GHUser.class, "getSuspendedAt", Date.class, Instant.class); - verifyBridgeMethods(GHWorkflowJob.class, "getStartedAt", Date.class, Instant.class); - verifyBridgeMethods(GHWorkflowJob.class, "getCompletedAt", Date.class, Instant.class); - verifyBridgeMethods(GHWorkflowJob.class, "getStartedAt", Date.class, Instant.class); - verifyBridgeMethods(GHWorkflowJob.class, "getCompletedAt", Date.class, Instant.class); - verifyBridgeMethods(GHWorkflowRun.class, "getRunStartedAt", Date.class, Instant.class); - verifyBridgeMethods(GHWorkflowRun.HeadCommit.class, "getTimestamp", Date.class, Instant.class); - verifyBridgeMethods(GitCommit.class, "getAuthoredDate", Date.class, Instant.class); - verifyBridgeMethods(GitCommit.class, "getCommitDate", Date.class, Instant.class); - verifyBridgeMethods(GitUser.class, "getDate", Date.class, Instant.class); } /** diff --git a/src/test/java/org/kohsuke/github/CommitTest.java b/src/test/java/org/kohsuke/github/CommitTest.java index cd429fc96c..746fec1e38 100644 --- a/src/test/java/org/kohsuke/github/CommitTest.java +++ b/src/test/java/org/kohsuke/github/CommitTest.java @@ -26,45 +26,15 @@ public CommitTest() { } /** - * Commit date not null. - * - * @throws Exception - * the exception - */ - @Test // issue 883 - public void commitDateNotNull() throws Exception { - GHRepository repo = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = repo.getCommit("865a49d2e86c24c5777985f0f103e975c4b765b9"); - - assertThat(commit.getCommitShortInfo().getAuthoredDate().getEpochSecond(), equalTo(1609207093L)); - assertThat(commit.getCommitShortInfo().getAuthoredDate(), - equalTo(commit.getCommitShortInfo().getAuthor().getDate())); - assertThat(commit.getCommitShortInfo().getCommitDate().getEpochSecond(), equalTo(1609207652L)); - assertThat(commit.getCommitShortInfo().getCommitDate(), - equalTo(commit.getCommitShortInfo().getCommitter().getDate())); - } - - /** - * Commit signature verification. + * Last status. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ - @Test // issue 737 - public void commitSignatureVerification() throws Exception { - GHRepository repo = gitHub.getRepository("stapler/stapler"); - PagedIterable commits = repo.queryCommits().path("pom.xml").list(); - for (GHCommit commit : Iterables.limit(commits, 10)) { - GHCommit expected = repo.getCommit(commit.getSHA1()); - assertThat(commit.getCommitShortInfo().getVerification().isVerified(), - equalTo(expected.getCommitShortInfo().getVerification().isVerified())); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(expected.getCommitShortInfo().getVerification().getReason())); - assertThat(commit.getCommitShortInfo().getVerification().getSignature(), - equalTo(expected.getCommitShortInfo().getVerification().getSignature())); - assertThat(commit.getCommitShortInfo().getVerification().getPayload(), - equalTo(expected.getCommitShortInfo().getVerification().getPayload())); - } + @Test // issue 152 + public void lastStatus() throws IOException { + GHTag t = gitHub.getRepository("stapler/stapler").listTags().iterator().next(); + assertThat(t.getCommit().getLastStatus(), notNullValue()); } /** @@ -84,84 +54,17 @@ public void getFiles() throws Exception { } /** - * Tests the commit message. + * Test list files where there are less than 300 files in a commit. * * @throws Exception * the exception */ - @Test - public void getMessage() throws Exception { + @Test // issue 1669 + public void listFilesWhereCommitHasSmallChange() throws Exception { GHRepository repo = getRepository(); GHCommit commit = repo.getCommit("dabf0e89fe7107d6e294a924561533ecf80f2384"); - assertThat(commit.getCommitShortInfo().getMessage(), notNullValue()); - assertThat(commit.getCommitShortInfo().getMessage(), equalTo("A commit with a few files")); - } - - /** - * Last status. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test // issue 152 - public void lastStatus() throws IOException { - GHTag t = gitHub.getRepository("stapler/stapler").listTags().iterator().next(); - assertThat(t.getCommit().getLastStatus(), notNullValue()); - } - - /** - * List branches where head. - * - * @throws Exception - * the exception - */ - @Test - public void listBranchesWhereHead() throws Exception { - GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); - - GHCommit commit = repo.getCommit("ab92e13c0fc844fd51a379a48a3ad0b18231215c"); - - assertThat("Commit which was supposed to be HEAD in the \"main\" branch was not found.", - commit.listBranchesWhereHead() - .toList() - .stream() - .findFirst() - .filter(it -> it.getName().equals("main")) - .isPresent()); - } - - /** - * List branches where head 2 heads. - * - * @throws Exception - * the exception - */ - @Test - public void listBranchesWhereHead2Heads() throws Exception { - GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); - - GHCommit commit = repo.getCommit("ab92e13c0fc844fd51a379a48a3ad0b18231215c"); - - assertThat("Commit which was supposed to be HEAD in 2 branches was not found as such.", - commit.listBranchesWhereHead().toList().size(), - equalTo(2)); - } - - /** - * List branches where head of commit with head nowhere. - * - * @throws Exception - * the exception - */ - @Test - public void listBranchesWhereHeadOfCommitWithHeadNowhere() throws Exception { - GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); - - GHCommit commit = repo.getCommit("7460916bfb8e9966d6b9d3e8ae378c82c6b8e43e"); - - assertThat("Commit which was not supposed to be HEAD in any branch was found as HEAD.", - commit.listBranchesWhereHead().toList().isEmpty()); + assertThat(commit.listFiles().toList().size(), equalTo(28)); } /** @@ -179,76 +82,18 @@ public void listFilesWhereCommitHasLargeChange() throws Exception { } /** - * Test list files where there are less than 300 files in a commit. + * Tests the commit message. * * @throws Exception * the exception */ - @Test // issue 1669 - public void listFilesWhereCommitHasSmallChange() throws Exception { + @Test + public void getMessage() throws Exception { GHRepository repo = getRepository(); GHCommit commit = repo.getCommit("dabf0e89fe7107d6e294a924561533ecf80f2384"); - assertThat(commit.listFiles().toList().size(), equalTo(28)); - } - - /** - * List pull requests. - * - * @throws Exception - * the exception - */ - @Test - public void listPullRequests() throws Exception { - GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); - Integer prNumber = 2; - - GHCommit commit = repo.getCommit("6b9956fe8c3d030dbc49c9d4c4166b0ceb4198fc"); - - List listedPrs = commit.listPullRequests().toList(); - - assertThat(1, equalTo(listedPrs.size())); - - assertThat("Pull request " + prNumber + " not found by searching from commit.", - listedPrs.stream().findFirst().filter(it -> it.getNumber() == prNumber).isPresent()); - } - - /** - * List pull requests of commit with 2 pull requests. - * - * @throws Exception - * the exception - */ - @Test - public void listPullRequestsOfCommitWith2PullRequests() throws Exception { - GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); - Integer[] expectedPrs = new Integer[]{ 1, 2 }; - - GHCommit commit = repo.getCommit("442aa213f924a5984856f16e52a18153aaf41ad3"); - - List listedPrs = commit.listPullRequests().toList(); - - assertThat(2, equalTo(listedPrs.size())); - - listedPrs.stream() - .forEach(pr -> assertThat("PR#" + pr.getNumber() + " not expected to be matched.", - Arrays.stream(expectedPrs).anyMatch(prNumber -> prNumber.equals(pr.getNumber())))); - } - - /** - * List pull requests of not included commit. - * - * @throws Exception - * the exception - */ - @Test - public void listPullRequestsOfNotIncludedCommit() throws Exception { - GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); - - GHCommit commit = repo.getCommit("f66f7ca691ace6f4a9230292efb932b49214d72c"); - - assertThat("The commit is supposed to be not part of any pull request", - commit.listPullRequests().toList().isEmpty()); + assertThat(commit.getCommitShortInfo().getMessage(), notNullValue()); + assertThat(commit.getCommitShortInfo().getMessage(), equalTo("A commit with a few files")); } /** @@ -338,8 +183,159 @@ public void testQueryCommits() throws Exception { } - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("CommitTest"); + /** + * List pull requests of not included commit. + * + * @throws Exception + * the exception + */ + @Test + public void listPullRequestsOfNotIncludedCommit() throws Exception { + GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); + + GHCommit commit = repo.getCommit("f66f7ca691ace6f4a9230292efb932b49214d72c"); + + assertThat("The commit is supposed to be not part of any pull request", + commit.listPullRequests().toList().isEmpty()); + } + + /** + * List pull requests. + * + * @throws Exception + * the exception + */ + @Test + public void listPullRequests() throws Exception { + GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); + Integer prNumber = 2; + + GHCommit commit = repo.getCommit("6b9956fe8c3d030dbc49c9d4c4166b0ceb4198fc"); + + List listedPrs = commit.listPullRequests().toList(); + + assertThat(1, equalTo(listedPrs.size())); + + assertThat("Pull request " + prNumber + " not found by searching from commit.", + listedPrs.stream().findFirst().filter(it -> it.getNumber() == prNumber).isPresent()); + } + + /** + * List pull requests of commit with 2 pull requests. + * + * @throws Exception + * the exception + */ + @Test + public void listPullRequestsOfCommitWith2PullRequests() throws Exception { + GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); + Integer[] expectedPrs = new Integer[]{ 1, 2 }; + + GHCommit commit = repo.getCommit("442aa213f924a5984856f16e52a18153aaf41ad3"); + + List listedPrs = commit.listPullRequests().toList(); + + assertThat(2, equalTo(listedPrs.size())); + + listedPrs.stream() + .forEach(pr -> assertThat("PR#" + pr.getNumber() + " not expected to be matched.", + Arrays.stream(expectedPrs).anyMatch(prNumber -> prNumber.equals(pr.getNumber())))); + } + + /** + * List branches where head. + * + * @throws Exception + * the exception + */ + @Test + public void listBranchesWhereHead() throws Exception { + GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); + + GHCommit commit = repo.getCommit("ab92e13c0fc844fd51a379a48a3ad0b18231215c"); + + assertThat("Commit which was supposed to be HEAD in the \"main\" branch was not found.", + commit.listBranchesWhereHead() + .toList() + .stream() + .findFirst() + .filter(it -> it.getName().equals("main")) + .isPresent()); + } + + /** + * List branches where head 2 heads. + * + * @throws Exception + * the exception + */ + @Test + public void listBranchesWhereHead2Heads() throws Exception { + GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); + + GHCommit commit = repo.getCommit("ab92e13c0fc844fd51a379a48a3ad0b18231215c"); + + assertThat("Commit which was supposed to be HEAD in 2 branches was not found as such.", + commit.listBranchesWhereHead().toList().size(), + equalTo(2)); + } + + /** + * List branches where head of commit with head nowhere. + * + * @throws Exception + * the exception + */ + @Test + public void listBranchesWhereHeadOfCommitWithHeadNowhere() throws Exception { + GHRepository repo = gitHub.getOrganization("hub4j-test-org").getRepository("listPrsListHeads"); + + GHCommit commit = repo.getCommit("7460916bfb8e9966d6b9d3e8ae378c82c6b8e43e"); + + assertThat("Commit which was not supposed to be HEAD in any branch was found as HEAD.", + commit.listBranchesWhereHead().toList().isEmpty()); + } + + /** + * Commit signature verification. + * + * @throws Exception + * the exception + */ + @Test // issue 737 + public void commitSignatureVerification() throws Exception { + GHRepository repo = gitHub.getRepository("stapler/stapler"); + PagedIterable commits = repo.queryCommits().path("pom.xml").list(); + for (GHCommit commit : Iterables.limit(commits, 10)) { + GHCommit expected = repo.getCommit(commit.getSHA1()); + assertThat(commit.getCommitShortInfo().getVerification().isVerified(), + equalTo(expected.getCommitShortInfo().getVerification().isVerified())); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), + equalTo(expected.getCommitShortInfo().getVerification().getReason())); + assertThat(commit.getCommitShortInfo().getVerification().getSignature(), + equalTo(expected.getCommitShortInfo().getVerification().getSignature())); + assertThat(commit.getCommitShortInfo().getVerification().getPayload(), + equalTo(expected.getCommitShortInfo().getVerification().getPayload())); + } + } + + /** + * Commit date not null. + * + * @throws Exception + * the exception + */ + @Test // issue 883 + public void commitDateNotNull() throws Exception { + GHRepository repo = gitHub.getRepository("hub4j/github-api"); + GHCommit commit = repo.getCommit("865a49d2e86c24c5777985f0f103e975c4b765b9"); + + assertThat(commit.getCommitShortInfo().getAuthoredDate().toInstant().getEpochSecond(), equalTo(1609207093L)); + assertThat(commit.getCommitShortInfo().getAuthoredDate(), + equalTo(commit.getCommitShortInfo().getAuthor().getDate())); + assertThat(commit.getCommitShortInfo().getCommitDate().toInstant().getEpochSecond(), equalTo(1609207652L)); + assertThat(commit.getCommitShortInfo().getCommitDate(), + equalTo(commit.getCommitShortInfo().getCommitter().getDate())); } /** @@ -352,4 +348,8 @@ private GHRepository getRepository(GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("CommitTest"); + } } diff --git a/src/test/java/org/kohsuke/github/EnterpriseManagedSupportTest.java b/src/test/java/org/kohsuke/github/EnterpriseManagedSupportTest.java index c8d7779c5b..ad2c4c63fe 100644 --- a/src/test/java/org/kohsuke/github/EnterpriseManagedSupportTest.java +++ b/src/test/java/org/kohsuke/github/EnterpriseManagedSupportTest.java @@ -14,112 +14,73 @@ */ public class EnterpriseManagedSupportTest extends AbstractGitHubWireMockTest { + /** + * Create default EnterpriseManagedSupportTest instance + */ + public EnterpriseManagedSupportTest() { + } + private static final String NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR = "{\"message\":\"This organization is not part of externally managed enterprise.\"," + "\"documentation_url\": \"https://docs.github.com/rest/teams/external-groups#list-external-groups-in-an-organization\"}"; - private static final String TEAM_CANNOT_BE_EXTERNALLY_MANAGED_ERROR = "{\"message\":\"This team cannot be externally managed since it has explicit members.\"," - + "\"documentation_url\": \"https://docs.github.com/rest/teams/external-groups#list-a-connection-between-an-external-group-and-a-team\"}"; - private static final String UNKNOWN_ERROR = "{\"message\":\"Unknown error\"," + "\"documentation_url\": \"https://docs.github.com/rest/unknown#unknown\"}"; - /** - * Create default EnterpriseManagedSupportTest instance - */ - public EnterpriseManagedSupportTest() { - } + private static final String TEAM_CANNOT_BE_EXTERNALLY_MANAGED_ERROR = "{\"message\":\"This team cannot be externally managed since it has explicit members.\"," + + "\"documentation_url\": \"https://docs.github.com/rest/teams/external-groups#list-a-connection-between-an-external-group-and-a-team\"}"; /** - * Test to validate compliant use case. + * Test to ensure that only HttpExceptions are handled * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testHandleEmbeddedNotPartOfExternallyManagedEnterpriseHttpException() throws IOException { + public void testIgnoreNonHttpException() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - final HttpException inputCause = new HttpException(NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR, - 400, - "Error", - org.getUrl().toString()); + final GHException inputCause = new GHException("Cause"); final GHException inputException = new GHException("Test", inputCause); final Optional maybeException = EnterpriseManagedSupport.forOrganization(org) .filterException(inputException); - assertThat(maybeException.isPresent(), is(true)); - - final GHException exception = maybeException.get(); - - assertThat(exception.getMessage(), - equalTo(EnterpriseManagedSupport.COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS)); - - final Throwable cause = exception.getCause(); - - assertThat(cause, instanceOf(GHNotExternallyManagedEnterpriseException.class)); - - final GHNotExternallyManagedEnterpriseException failure = (GHNotExternallyManagedEnterpriseException) cause; - - assertThat(failure.getCause(), is(inputCause)); - assertThat(failure.getMessage(), - equalTo(EnterpriseManagedSupport.COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS)); - - final GHError error = failure.getError(); - - assertThat(error, notNullValue()); - assertThat(error.getMessage(), - equalTo(EnterpriseManagedSupport.NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR)); - assertThat(error.getDocumentationUrl(), notNullValue()); + assertThat(maybeException.isPresent(), is(false)); } /** - * Test to validate another compliant use case. + * Test to ensure that only BadRequests HttpExceptions are handled * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testHandleTeamCannotBeExternallyManagedHttpException() throws IOException { + public void testIgnoreNonBadRequestExceptions() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - final HttpException inputException = new HttpException(TEAM_CANNOT_BE_EXTERNALLY_MANAGED_ERROR, - 400, + final HttpException inputCause = new HttpException(NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR, + 404, "Error", org.getUrl().toString()); + final GHException inputException = new GHException("Test", inputCause); - final Optional maybeException = EnterpriseManagedSupport.forOrganization(org) - .filterException(inputException, "Scenario"); - - assertThat(maybeException.isPresent(), is(true)); - - final GHIOException exception = maybeException.get(); - - assertThat(exception.getMessage(), equalTo("Scenario")); - assertThat(exception.getCause(), is(inputException)); - - assertThat(exception, instanceOf(GHTeamCannotBeExternallyManagedException.class)); - - final GHTeamCannotBeExternallyManagedException failure = (GHTeamCannotBeExternallyManagedException) exception; - - final GHError error = failure.getError(); + final Optional maybeException = EnterpriseManagedSupport.forOrganization(org) + .filterException(inputException); - assertThat(error, notNullValue()); - assertThat(error.getMessage(), equalTo(EnterpriseManagedSupport.TEAM_CANNOT_BE_EXTERNALLY_MANAGED_ERROR)); - assertThat(error.getDocumentationUrl(), notNullValue()); + assertThat(maybeException.isPresent(), is(false)); } /** - * Test to ensure that only BadRequests HttpExceptions with known error message are handled + * Test to ensure that only BadRequests HttpExceptions with parseable JSON payload are handled * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testIgnoreBadRequestsWithUnknownErrorMessage() throws IOException { + public void testIgnoreBadRequestsWithUnparseableJson() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - final HttpException inputCause = new HttpException(UNKNOWN_ERROR, 400, "Error", org.getUrl().toString()); + final HttpException inputCause = new HttpException("Error", 400, "Error", org.getUrl().toString()); final GHException inputException = new GHException("Test", inputCause); final Optional maybeException = EnterpriseManagedSupport.forOrganization(org) @@ -129,16 +90,16 @@ public void testIgnoreBadRequestsWithUnknownErrorMessage() throws IOException { } /** - * Test to ensure that only BadRequests HttpExceptions with parseable JSON payload are handled + * Test to ensure that only BadRequests HttpExceptions with known error message are handled * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testIgnoreBadRequestsWithUnparseableJson() throws IOException { + public void testIgnoreBadRequestsWithUnknownErrorMessage() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - final HttpException inputCause = new HttpException("Error", 400, "Error", org.getUrl().toString()); + final HttpException inputCause = new HttpException(UNKNOWN_ERROR, 400, "Error", org.getUrl().toString()); final GHException inputException = new GHException("Test", inputCause); final Optional maybeException = EnterpriseManagedSupport.forOrganization(org) @@ -148,17 +109,17 @@ public void testIgnoreBadRequestsWithUnparseableJson() throws IOException { } /** - * Test to ensure that only BadRequests HttpExceptions are handled + * Test to validate compliant use case. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testIgnoreNonBadRequestExceptions() throws IOException { + public void testHandleEmbeddedNotPartOfExternallyManagedEnterpriseHttpException() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); final HttpException inputCause = new HttpException(NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR, - 404, + 400, "Error", org.getUrl().toString()); final GHException inputException = new GHException("Test", inputCause); @@ -166,25 +127,64 @@ public void testIgnoreNonBadRequestExceptions() throws IOException { final Optional maybeException = EnterpriseManagedSupport.forOrganization(org) .filterException(inputException); - assertThat(maybeException.isPresent(), is(false)); + assertThat(maybeException.isPresent(), is(true)); + + final GHException exception = maybeException.get(); + + assertThat(exception.getMessage(), + equalTo(EnterpriseManagedSupport.COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS)); + + final Throwable cause = exception.getCause(); + + assertThat(cause, instanceOf(GHNotExternallyManagedEnterpriseException.class)); + + final GHNotExternallyManagedEnterpriseException failure = (GHNotExternallyManagedEnterpriseException) cause; + + assertThat(failure.getCause(), is(inputCause)); + assertThat(failure.getMessage(), + equalTo(EnterpriseManagedSupport.COULD_NOT_RETRIEVE_ORGANIZATION_EXTERNAL_GROUPS)); + + final GHError error = failure.getError(); + + assertThat(error, notNullValue()); + assertThat(error.getMessage(), + equalTo(EnterpriseManagedSupport.NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR)); + assertThat(error.getDocumentationUrl(), notNullValue()); } /** - * Test to ensure that only HttpExceptions are handled + * Test to validate another compliant use case. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testIgnoreNonHttpException() throws IOException { + public void testHandleTeamCannotBeExternallyManagedHttpException() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - final GHException inputCause = new GHException("Cause"); - final GHException inputException = new GHException("Test", inputCause); + final HttpException inputException = new HttpException(TEAM_CANNOT_BE_EXTERNALLY_MANAGED_ERROR, + 400, + "Error", + org.getUrl().toString()); - final Optional maybeException = EnterpriseManagedSupport.forOrganization(org) - .filterException(inputException); + final Optional maybeException = EnterpriseManagedSupport.forOrganization(org) + .filterException(inputException, "Scenario"); - assertThat(maybeException.isPresent(), is(false)); + assertThat(maybeException.isPresent(), is(true)); + + final GHIOException exception = maybeException.get(); + + assertThat(exception.getMessage(), equalTo("Scenario")); + assertThat(exception.getCause(), is(inputException)); + + assertThat(exception, instanceOf(GHTeamCannotBeExternallyManagedException.class)); + + final GHTeamCannotBeExternallyManagedException failure = (GHTeamCannotBeExternallyManagedException) exception; + + final GHError error = failure.getError(); + + assertThat(error, notNullValue()); + assertThat(error.getMessage(), equalTo(EnterpriseManagedSupport.TEAM_CANNOT_BE_EXTERNALLY_MANAGED_ERROR)); + assertThat(error.getDocumentationUrl(), notNullValue()); } } diff --git a/src/test/java/org/kohsuke/github/EnumTest.java b/src/test/java/org/kohsuke/github/EnumTest.java index 5a2df1ef82..2e509b5aec 100644 --- a/src/test/java/org/kohsuke/github/EnumTest.java +++ b/src/test/java/org/kohsuke/github/EnumTest.java @@ -27,7 +27,7 @@ public void touchEnums() { assertThat(GHCheckRun.Conclusion.values().length, equalTo(9)); assertThat(GHCheckRun.Status.values().length, equalTo(4)); - assertThat(GHCommentAuthorAssociation.values().length, equalTo(9)); + assertThat(GHCommentAuthorAssociation.values().length, equalTo(8)); assertThat(GHCommitSearchBuilder.Sort.values().length, equalTo(2)); @@ -54,7 +54,7 @@ public void touchEnums() { assertThat(GHIssueState.values().length, equalTo(3)); - assertThat(GHIssueStateReason.values().length, equalTo(4)); + assertThat(GHIssueStateReason.values().length, equalTo(3)); assertThat(GHMarketplaceAccountType.values().length, equalTo(2)); diff --git a/src/test/java/org/kohsuke/github/ExternalGroupsTestingSupport.java b/src/test/java/org/kohsuke/github/ExternalGroupsTestingSupport.java index 4c0d34cfc3..73cb162ec5 100644 --- a/src/test/java/org/kohsuke/github/ExternalGroupsTestingSupport.java +++ b/src/test/java/org/kohsuke/github/ExternalGroupsTestingSupport.java @@ -14,12 +14,51 @@ */ class ExternalGroupsTestingSupport { - private static class IsExternalGroupSummary extends TypeSafeDiagnosingMatcher { - @Override - public void describeTo(Description description) { - description.appendText("is a summary"); + static GHExternalGroup findExternalGroup(List groups, Predicate predicate) { + return groups.stream().filter(predicate).findFirst().orElseThrow(AssertionError::new); + } + + static Predicate hasName(String anObject) { + return g -> g.getName().equals(anObject); + } + + static List groupSummary(List groups) { + return collect(groups, ExternalGroupsTestingSupport::describeGroup); + } + + static List teamSummary(GHExternalGroup sut) { + return collect(sut.getTeams(), ExternalGroupsTestingSupport::describeTeam); + } + + static List membersSummary(GHExternalGroup sut) { + return collect(sut.getMembers(), ExternalGroupsTestingSupport::describeMember); + } + + private static List collect(List collection, Function transformation) { + return collection.stream().map(transformation).collect(Collectors.toList()); + } + + private static String describeGroup(GHExternalGroup g) { + return String.format("%d:%s", g.getId(), g.getName()); + } + + private static String describeTeam(GHExternalGroup.GHLinkedTeam t) { + return String.format("%d:%s", t.getId(), t.getName()); + } + + private static String describeMember(GHExternalGroup.GHLinkedExternalMember m) { + return String.format("%d:%s:%s:%s", m.getId(), m.getLogin(), m.getName(), m.getEmail()); + } + + static class Matchers { + + static Matcher isExternalGroupSummary() { + return new IsExternalGroupSummary(); } + } + + private static class IsExternalGroupSummary extends TypeSafeDiagnosingMatcher { @Override protected boolean matchesSafely(GHExternalGroup group, Description mismatchDescription) { boolean result = true; @@ -51,49 +90,10 @@ protected boolean matchesSafely(GHExternalGroup group, Description mismatchDescr } return result; } - } - - static class Matchers { - static Matcher isExternalGroupSummary() { - return new IsExternalGroupSummary(); + @Override + public void describeTo(Description description) { + description.appendText("is a summary"); } - - } - - private static List collect(List collection, Function transformation) { - return collection.stream().map(transformation).collect(Collectors.toList()); - } - - private static String describeGroup(GHExternalGroup g) { - return String.format("%d:%s", g.getId(), g.getName()); - } - - private static String describeMember(GHExternalGroup.GHLinkedExternalMember m) { - return String.format("%d:%s:%s:%s", m.getId(), m.getLogin(), m.getName(), m.getEmail()); - } - - private static String describeTeam(GHExternalGroup.GHLinkedTeam t) { - return String.format("%d:%s", t.getId(), t.getName()); - } - - static GHExternalGroup findExternalGroup(List groups, Predicate predicate) { - return groups.stream().filter(predicate).findFirst().orElseThrow(AssertionError::new); - } - - static List groupSummary(List groups) { - return collect(groups, ExternalGroupsTestingSupport::describeGroup); - } - - static Predicate hasName(String anObject) { - return g -> g.getName().equals(anObject); - } - - static List membersSummary(GHExternalGroup sut) { - return collect(sut.getMembers(), ExternalGroupsTestingSupport::describeMember); - } - - static List teamSummary(GHExternalGroup sut) { - return collect(sut.getTeams(), ExternalGroupsTestingSupport::describeTeam); } } diff --git a/src/test/java/org/kohsuke/github/GHAppExtendedTest.java b/src/test/java/org/kohsuke/github/GHAppExtendedTest.java index 3ef03419cc..84e3566a55 100644 --- a/src/test/java/org/kohsuke/github/GHAppExtendedTest.java +++ b/src/test/java/org/kohsuke/github/GHAppExtendedTest.java @@ -14,14 +14,32 @@ */ public class GHAppExtendedTest extends AbstractGitHubWireMockTest { - private static final String APP_SLUG = "ghapi-test-app-4"; - /** * Create default GHAppExtendedTest instance */ public GHAppExtendedTest() { } + private static final String APP_SLUG = "ghapi-test-app-4"; + + /** + * Gets the GitHub App by its slug. + * + * @throws IOException + * An IOException has occurred. + */ + @Test + public void getAppBySlugTest() throws IOException { + GHApp app = gitHub.getApp(APP_SLUG); + + assertThat(app.getId(), is((long) 330762)); + assertThat(app.getSlug(), equalTo(APP_SLUG)); + assertThat(app.getName(), equalTo("GHApi Test app 4")); + assertThat(app.getExternalUrl(), equalTo("https://github.com/organizations/hub4j-test-org")); + assertThat(app.getHtmlUrl().toString(), equalTo("https://github.com/apps/ghapi-test-app-4")); + assertThat(app.getDescription(), equalTo("An app to test the GitHub getApp(slug) method.")); + } + /** * Tests App creation via the App Manifest Flow. * @@ -44,22 +62,4 @@ public void createAppByManifestFlowTest() throws IOException { } - /** - * Gets the GitHub App by its slug. - * - * @throws IOException - * An IOException has occurred. - */ - @Test - public void getAppBySlugTest() throws IOException { - GHApp app = gitHub.getApp(APP_SLUG); - - assertThat(app.getId(), is((long) 330762)); - assertThat(app.getSlug(), equalTo(APP_SLUG)); - assertThat(app.getName(), equalTo("GHApi Test app 4")); - assertThat(app.getExternalUrl(), equalTo("https://github.com/organizations/hub4j-test-org")); - assertThat(app.getHtmlUrl().toString(), equalTo("https://github.com/apps/ghapi-test-app-4")); - assertThat(app.getDescription(), equalTo("An app to test the GitHub getApp(slug) method.")); - } - } diff --git a/src/test/java/org/kohsuke/github/GHAppInstallationTest.java b/src/test/java/org/kohsuke/github/GHAppInstallationTest.java index 04f4f2529f..46c51b7b64 100644 --- a/src/test/java/org/kohsuke/github/GHAppInstallationTest.java +++ b/src/test/java/org/kohsuke/github/GHAppInstallationTest.java @@ -3,10 +3,10 @@ import org.junit.Test; import java.io.IOException; -import java.time.Instant; import java.time.LocalDateTime; import java.time.Month; import java.time.ZoneOffset; +import java.util.Date; import java.util.List; import static org.hamcrest.Matchers.*; @@ -25,20 +25,20 @@ public GHAppInstallationTest() { } /** - * Test list repositories no permissions. + * Test list repositories two repos. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetMarketplaceAccount() throws IOException { - GHAppInstallation appInstallation = getAppInstallationWithToken(jwtProvider3.getEncodedAuthorization()); + public void testListRepositoriesTwoRepos() throws IOException { + GHAppInstallation appInstallation = getAppInstallationWithToken(jwtProvider1.getEncodedAuthorization()); - GHMarketplaceAccountPlan marketplaceAccount = appInstallation.getMarketplaceAccount(); - GHMarketplacePlanTest.testMarketplaceAccount(marketplaceAccount); + List repositories = appInstallation.listRepositories().toList(); - GHMarketplaceAccountPlan plan = marketplaceAccount.getPlan(); - assertThat(plan.getType(), equalTo(GHMarketplaceAccountType.ORGANIZATION)); + assertThat(repositories.size(), equalTo(2)); + assertThat(repositories.stream().map(GHRepository::getName).toArray(), + arrayContainingInAnyOrder("empty", "test-readme")); } /** @@ -56,20 +56,20 @@ public void testListRepositoriesNoPermissions() throws IOException { } /** - * Test list repositories two repos. + * Test list repositories no permissions. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testListRepositoriesTwoRepos() throws IOException { - GHAppInstallation appInstallation = getAppInstallationWithToken(jwtProvider1.getEncodedAuthorization()); + public void testGetMarketplaceAccount() throws IOException { + GHAppInstallation appInstallation = getAppInstallationWithToken(jwtProvider3.getEncodedAuthorization()); - List repositories = appInstallation.listRepositories().toList(); + GHMarketplaceAccountPlan marketplaceAccount = appInstallation.getMarketplaceAccount(); + GHMarketplacePlanTest.testMarketplaceAccount(marketplaceAccount); - assertThat(repositories.size(), equalTo(2)); - assertThat(repositories.stream().map(GHRepository::getName).toArray(), - arrayContainingInAnyOrder("empty", "test-readme")); + GHMarketplaceAccountPlan plan = marketplaceAccount.getPlan(); + assertThat(plan.getType(), equalTo(GHMarketplaceAccountType.ORGANIZATION)); } /** @@ -85,9 +85,9 @@ public void testListSuspendedInstallation() throws IOException { final GHUser suspendedBy = appInstallation.getSuspendedBy(); assertThat(suspendedBy.getLogin(), equalTo("gilday")); - final Instant suspendedAt = appInstallation.getSuspendedAt(); - final Instant expectedSuspendedAt = LocalDateTime.of(2024, Month.FEBRUARY, 26, 2, 43, 12) - .toInstant(ZoneOffset.UTC); + final Date suspendedAt = appInstallation.getSuspendedAt(); + final Date expectedSuspendedAt = Date + .from(LocalDateTime.of(2024, Month.FEBRUARY, 26, 2, 43, 12).toInstant(ZoneOffset.UTC)); assertThat(suspendedAt, equalTo(expectedSuspendedAt)); } diff --git a/src/test/java/org/kohsuke/github/GHAppTest.java b/src/test/java/org/kohsuke/github/GHAppTest.java index 420bc16466..27a3023636 100644 --- a/src/test/java/org/kohsuke/github/GHAppTest.java +++ b/src/test/java/org/kohsuke/github/GHAppTest.java @@ -5,10 +5,6 @@ import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -34,115 +30,81 @@ public GHAppTest() { } /** - * Creates the token. + * Gets the git hub builder. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the git hub builder */ - @Test - public void createToken() throws IOException { - GHApp app = gitHub.getApp(); - GHAppInstallation installation = app.getInstallationByUser("bogus"); - - Map permissions = new HashMap(); - permissions.put("checks", GHPermissionType.WRITE); - permissions.put("pull_requests", GHPermissionType.WRITE); - permissions.put("contents", GHPermissionType.READ); - permissions.put("metadata", GHPermissionType.READ); - - // Create token specifying both permissions and repository ids - GHAppInstallationToken installationToken = installation.createToken(permissions) - .repositoryIds(Collections.singletonList((long) 111111111)) - .create(); - - assertThat(installationToken.getToken(), is("bogus")); - assertThat(installation.getPermissions(), is(permissions)); - assertThat(installationToken.getRepositorySelection(), is(GHRepositorySelection.SELECTED)); - assertThat(installationToken.getExpiresAt(), is(GitHubClient.parseInstant("2019-08-10T05:54:58Z"))); - - GHRepository repository = installationToken.getRepositories().get(0); - assertThat(installationToken.getRepositories().size(), is(1)); - assertThat(repository.getId(), is((long) 111111111)); - assertThat(repository.getName(), is("bogus")); - - // Create token with no payload - GHAppInstallationToken installationToken2 = installation.createToken().create(); - - assertThat(installationToken2.getToken(), is("bogus")); - assertThat(installationToken2.getPermissions().size(), is(4)); - assertThat(installationToken2.getRepositorySelection(), is(GHRepositorySelection.ALL)); - assertThat(installationToken2.getExpiresAt(), is(GitHubClient.parseInstant("2019-12-19T12:27:59Z"))); - - assertThat(installationToken2.getRepositories(), nullValue());; + protected GitHubBuilder getGitHubBuilder() { + return super.getGitHubBuilder() + // ensure that only JWT will be used against the tests below + .withOAuthToken(null, null) + // Note that we used to provide a bogus token here and to rely on (apparently) manually crafted/edited + // Wiremock recordings, so most of the tests cannot actually be executed against GitHub without + // relying on the Wiremock recordings. + // Some tests have been updated, though (getGitHubApp in particular). + .withAuthorizationProvider(jwtProvider1); } /** - * Creates the token with repositories. + * Gets the git hub app. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void createTokenWithRepositories() throws IOException { + public void getGitHubApp() throws IOException { GHApp app = gitHub.getApp(); - GHAppInstallation installation = app.getInstallationByUser("bogus"); - - // Create token specifying repositories (not repository_ids!) - GHAppInstallationToken installationToken = installation.createToken() - .repositories(Collections.singletonList("bogus")) - .create(); - - assertThat(installationToken.getToken(), is("bogus")); - assertThat(installationToken.getPermissions().entrySet(), hasSize(4)); - assertThat(installationToken.getRepositorySelection(), is(GHRepositorySelection.SELECTED)); - assertThat(installationToken.getExpiresAt(), is(GitHubClient.parseInstant("2022-07-27T21:38:33Z"))); - - GHRepository repository = installationToken.getRepositories().get(0); - assertThat(installationToken.getRepositories().size(), is(1)); - assertThat(repository.getId(), is((long) 11111111)); - assertThat(repository.getName(), is("bogus")); + assertThat(app.getId(), is((long) 82994)); + assertThat(app.getOwner().getId(), is((long) 7544739)); + assertThat(app.getOwner().getLogin(), is("hub4j-test-org")); + assertThat(app.getName(), is("GHApi Test app 1")); + assertThat(app.getSlug(), is("ghapi-test-app-1")); + assertThat(app.getDescription(), is("")); + assertThat(app.getExternalUrl(), is("http://localhost")); + assertThat(app.getHtmlUrl().toString(), is("https://github.com/apps/ghapi-test-app-1")); + assertThat(app.getCreatedAt(), is(GitHubClient.parseDate("2020-09-30T13:40:56Z"))); + assertThat(app.getUpdatedAt(), is(GitHubClient.parseDate("2020-09-30T13:40:56Z"))); + assertThat(app.getPermissions().size(), is(2)); + assertThat(app.getEvents().size(), is(0)); + assertThat(app.getInstallationsCount(), is((long) 1)); } /** - * Delete installation. + * List installations. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void deleteInstallation() throws IOException { + public void listInstallations() throws IOException { GHApp app = gitHub.getApp(); - GHAppInstallation installation = app.getInstallationByUser("bogus"); - try { - installation.deleteInstallation(); - } catch (IOException e) { - fail("deleteInstallation wasn't suppose to fail in this test"); - } + List installations = app.listInstallations().toList(); + assertThat(installations.size(), is(1)); + + GHAppInstallation appInstallation = installations.get(0); + testAppInstallation(appInstallation); } /** - * Gets the git hub app. + * List installations that have been updated since a given date. * * @throws IOException * Signals that an I/O exception has occurred. + * + * @throws ParseException + * Issue parsing date string. */ @Test - public void getGitHubApp() throws IOException { + public void listInstallationsSince() throws IOException, ParseException { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + Date localDate = simpleDateFormat.parse("2023-11-01"); GHApp app = gitHub.getApp(); - assertThat(app.getId(), is((long) 82994)); - assertThat(app.getOwner().getId(), is((long) 7544739)); - assertThat(app.getOwner().getLogin(), is("hub4j-test-org")); - assertThat(app.getOwner().getType(), is("Organization")); - assertThat(app.getName(), is("GHApi Test app 1")); - assertThat(app.getSlug(), is("ghapi-test-app-1")); - assertThat(app.getDescription(), is("")); - assertThat(app.getExternalUrl(), is("http://localhost")); - assertThat(app.getHtmlUrl().toString(), is("https://github.com/apps/ghapi-test-app-1")); - assertThat(app.getCreatedAt(), is(GitHubClient.parseInstant("2020-09-30T13:40:56Z"))); - assertThat(app.getUpdatedAt(), is(GitHubClient.parseInstant("2020-09-30T13:40:56Z"))); - assertThat(app.getPermissions().size(), is(2)); - assertThat(app.getEvents().size(), is(0)); - assertThat(app.getInstallationsCount(), is((long) 1)); + List installations = app.listInstallations(localDate).toList(); + assertThat(installations.size(), is(1)); + + GHAppInstallation appInstallation = installations.get(0); + testAppInstallation(appInstallation); } /** @@ -198,68 +160,90 @@ public void getInstallationByUser() throws IOException { } /** - * List installation requests. + * Delete installation. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void listInstallationRequests() throws IOException { + public void deleteInstallation() throws IOException { GHApp app = gitHub.getApp(); - List installations = app.listInstallationRequests().toList(); - assertThat(installations.size(), is(1)); - - GHAppInstallationRequest appInstallation = installations.get(0); - assertThat(appInstallation.getId(), is((long) 1037204)); - assertThat(appInstallation.getAccount().getId(), is((long) 195438329)); - assertThat(appInstallation.getAccount().getLogin(), is("approval-test")); - assertThat(appInstallation.getAccount().getType(), is("Organization")); - assertThat(appInstallation.getRequester().getId(), is((long) 195437694)); - assertThat(appInstallation.getRequester().getLogin(), is("kaladinstormblessed2")); - assertThat(appInstallation.getRequester().getType(), is("User")); - assertThat(appInstallation.getCreatedAt(), is(GitHubClient.parseInstant("2025-01-17T15:50:51Z"))); - assertThat(appInstallation.getNodeId(), is("MDMwOkludGVncmF0aW9uSW5zdGFsbGF0aW9uUmVxdWVzdDEwMzcyMDQ=")); + GHAppInstallation installation = app.getInstallationByUser("bogus"); + try { + installation.deleteInstallation(); + } catch (IOException e) { + fail("deleteInstallation wasn't suppose to fail in this test"); + } } /** - * List installations. + * Creates the token. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void listInstallations() throws IOException { + public void createToken() throws IOException { GHApp app = gitHub.getApp(); - List installations = app.listInstallations().toList(); - assertThat(installations.size(), is(1)); + GHAppInstallation installation = app.getInstallationByUser("bogus"); - GHAppInstallation appInstallation = installations.get(0); - testAppInstallation(appInstallation); + Map permissions = new HashMap(); + permissions.put("checks", GHPermissionType.WRITE); + permissions.put("pull_requests", GHPermissionType.WRITE); + permissions.put("contents", GHPermissionType.READ); + permissions.put("metadata", GHPermissionType.READ); + + // Create token specifying both permissions and repository ids + GHAppInstallationToken installationToken = installation.createToken(permissions) + .repositoryIds(Collections.singletonList((long) 111111111)) + .create(); + + assertThat(installationToken.getToken(), is("bogus")); + assertThat(installation.getPermissions(), is(permissions)); + assertThat(installationToken.getRepositorySelection(), is(GHRepositorySelection.SELECTED)); + assertThat(installationToken.getExpiresAt(), is(GitHubClient.parseDate("2019-08-10T05:54:58Z"))); + + GHRepository repository = installationToken.getRepositories().get(0); + assertThat(installationToken.getRepositories().size(), is(1)); + assertThat(repository.getId(), is((long) 111111111)); + assertThat(repository.getName(), is("bogus")); + + // Create token with no payload + GHAppInstallationToken installationToken2 = installation.createToken().create(); + + assertThat(installationToken2.getToken(), is("bogus")); + assertThat(installationToken2.getPermissions().size(), is(4)); + assertThat(installationToken2.getRepositorySelection(), is(GHRepositorySelection.ALL)); + assertThat(installationToken2.getExpiresAt(), is(GitHubClient.parseDate("2019-12-19T12:27:59Z"))); + + assertThat(installationToken2.getRepositories(), nullValue());; } /** - * List installations that have been updated since a given date. + * Creates the token with repositories. * * @throws IOException * Signals that an I/O exception has occurred. - * @throws ParseException - * Signals that a ParseException has occurred. - * */ @Test - public void listInstallationsSince() throws IOException, ParseException { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - Date localDate = simpleDateFormat.parse("2023-11-01"); - Instant localInstant = LocalDate.parse("2023-11-01", DateTimeFormatter.ISO_LOCAL_DATE) - .atStartOfDay() - .toInstant(ZoneOffset.UTC); + public void createTokenWithRepositories() throws IOException { GHApp app = gitHub.getApp(); - List installations = app.listInstallations(localDate).toList(); - assertThat(installations.size(), is(1)); + GHAppInstallation installation = app.getInstallationByUser("bogus"); - GHAppInstallation appInstallation = installations.get(0); - testAppInstallation(appInstallation); + // Create token specifying repositories (not repository_ids!) + GHAppInstallationToken installationToken = installation.createToken() + .repositories(Collections.singletonList("bogus")) + .create(); + + assertThat(installationToken.getToken(), is("bogus")); + assertThat(installationToken.getPermissions().entrySet(), hasSize(4)); + assertThat(installationToken.getRepositorySelection(), is(GHRepositorySelection.SELECTED)); + assertThat(installationToken.getExpiresAt(), is(GitHubClient.parseDate("2022-07-27T21:38:33Z"))); + + GHRepository repository = installationToken.getRepositories().get(0); + assertThat(installationToken.getRepositories().size(), is(1)); + assertThat(repository.getId(), is((long) 11111111)); + assertThat(repository.getName(), is("bogus")); } private void testAppInstallation(GHAppInstallation appInstallation) throws IOException { @@ -269,7 +253,6 @@ private void testAppInstallation(GHAppInstallation appInstallation) throws IOExc assertThat(appInstallation.getId(), is((long) 11111111)); assertThat(appAccount.getId(), is((long) 111111111)); assertThat(appAccount.login, is("bogus")); - assertThat(appAccount.getType(), is("Organization")); assertThat(appInstallation.getRepositorySelection(), is(GHRepositorySelection.SELECTED)); assertThat(appInstallation.getAccessTokenUrl(), endsWith("/app/installations/11111111/access_tokens")); assertThat(appInstallation.getRepositoriesUrl(), endsWith("/installation/repositories")); @@ -286,25 +269,9 @@ private void testAppInstallation(GHAppInstallation appInstallation) throws IOExc List events = Arrays.asList(GHEvent.PULL_REQUEST, GHEvent.PUSH); assertThat(appInstallation.getEvents(), containsInAnyOrder(events.toArray(new GHEvent[0]))); - assertThat(appInstallation.getCreatedAt(), is(GitHubClient.parseInstant("2019-07-04T01:19:36.000Z"))); - assertThat(appInstallation.getUpdatedAt(), is(GitHubClient.parseInstant("2019-07-30T22:48:09.000Z"))); + assertThat(appInstallation.getCreatedAt(), is(GitHubClient.parseDate("2019-07-04T01:19:36.000Z"))); + assertThat(appInstallation.getUpdatedAt(), is(GitHubClient.parseDate("2019-07-30T22:48:09.000Z"))); assertThat(appInstallation.getSingleFileName(), nullValue()); } - /** - * Gets the git hub builder. - * - * @return the git hub builder - */ - protected GitHubBuilder getGitHubBuilder() { - return super.getGitHubBuilder() - // ensure that only JWT will be used against the tests below - .withOAuthToken(null, null) - // Note that we used to provide a bogus token here and to rely on (apparently) manually crafted/edited - // Wiremock recordings, so most of the tests cannot actually be executed against GitHub without - // relying on the Wiremock recordings. - // Some tests have been updated, though (getGitHubApp in particular). - .withAuthorizationProvider(jwtProvider1); - } - } diff --git a/src/test/java/org/kohsuke/github/GHAuthenticatedAppInstallationTest.java b/src/test/java/org/kohsuke/github/GHAuthenticatedAppInstallationTest.java index 775af6712d..3786f22e37 100644 --- a/src/test/java/org/kohsuke/github/GHAuthenticatedAppInstallationTest.java +++ b/src/test/java/org/kohsuke/github/GHAuthenticatedAppInstallationTest.java @@ -21,6 +21,19 @@ public class GHAuthenticatedAppInstallationTest extends AbstractGHAppInstallatio public GHAuthenticatedAppInstallationTest() { } + /** + * Gets the git hub builder. + * + * @return the git hub builder + */ + @Override + protected GitHubBuilder getGitHubBuilder() { + AppInstallationAuthorizationProvider provider = new AppInstallationAuthorizationProvider( + app -> app.getInstallationByOrganization("hub4j-test-org"), + jwtProvider1); + return super.getGitHubBuilder().withAuthorizationProvider(provider); + } + /** * Test list repositories two repos. * @@ -38,17 +51,4 @@ public void testListRepositoriesTwoRepos() throws IOException { arrayContainingInAnyOrder("empty", "test-readme")); } - /** - * Gets the git hub builder. - * - * @return the git hub builder - */ - @Override - protected GitHubBuilder getGitHubBuilder() { - AppInstallationAuthorizationProvider provider = new AppInstallationAuthorizationProvider( - app -> app.getInstallationByOrganization("hub4j-test-org"), - jwtProvider1); - return super.getGitHubBuilder().withAuthorizationProvider(provider); - } - } diff --git a/src/test/java/org/kohsuke/github/GHAutolinkTest.java b/src/test/java/org/kohsuke/github/GHAutolinkTest.java deleted file mode 100644 index b337542ee1..0000000000 --- a/src/test/java/org/kohsuke/github/GHAutolinkTest.java +++ /dev/null @@ -1,205 +0,0 @@ -package org.kohsuke.github; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.util.List; - -import static org.hamcrest.Matchers.*; - -// TODO: Auto-generated Javadoc -/** - * The type Gh autolink test. - */ -public class GHAutolinkTest extends AbstractGitHubWireMockTest { - - private GHRepository repo; - - /** - * Instantiates a new Gh autolink test. - */ - public GHAutolinkTest() { - } - - /** - * Cleanup. - */ - @After - public void cleanup() { - if (repo != null) { - try { - PagedIterable autolinks = repo.listAutolinks(); - for (GHAutolink autolink : autolinks) { - try { - autolink.delete(); - } catch (Exception e) { - System.err.println("Failed to delete autolink: " + e.getMessage()); - } - } - } catch (Exception e) { - System.err.println("Cleanup failed: " + e.getMessage()); - } - } - } - - /** - * Sets up. - * - * @throws Exception - * the exception - */ - @Before - public void setUp() throws Exception { - repo = gitHub.getRepository("Alaurant/github-api-test"); - if (repo == null) { - throw new IllegalStateException("Failed to initialize repository"); - } - } - - /** - * Test create autolink. - * - * @throws Exception - * the exception - */ - @Test - public void testCreateAutolink() throws Exception { - String keyPrefix = "EXAMPLE-"; - String urlTemplate = "https://example.com/TICKET?q="; - boolean isAlphanumeric = true; - - GHAutolink autolink = repo.createAutolink() - .withKeyPrefix(keyPrefix) - .withUrlTemplate(urlTemplate) - .withIsAlphanumeric(isAlphanumeric) - .create(); - - assertThat(autolink.getId(), notNullValue()); - assertThat(autolink.getKeyPrefix(), equalTo(keyPrefix)); - assertThat(autolink.getUrlTemplate(), equalTo(urlTemplate)); - assertThat(autolink.isAlphanumeric(), equalTo(isAlphanumeric)); - assertThat(autolink.getOwner(), equalTo(repo)); - - autolink.delete(); - - } - - /** - * Test delete autolink. - * - * @throws Exception - * the exception - */ - @Test - public void testDeleteAutolink() throws Exception { - // Delete autolink using the instance method - GHAutolink autolink = repo.createAutolink() - .withKeyPrefix("DELETE-") - .withUrlTemplate("https://example.com/delete/") - .withIsAlphanumeric(true) - .create(); - - autolink.delete(); - - try { - repo.readAutolink(autolink.getId()); - fail("Expected GHFileNotFoundException"); - } catch (GHFileNotFoundException e) { - // Expected - } - - // Delete autolink using repository delete method - autolink = repo.createAutolink() - .withKeyPrefix("DELETED-") - .withUrlTemplate("https://example.com/delete2/") - .withIsAlphanumeric(true) - .create(); - - repo.deleteAutolink(autolink.getId()); - - try { - repo.readAutolink(autolink.getId()); - fail("Expected GHFileNotFoundException"); - } catch (GHFileNotFoundException e) { - // Expected - } - } - - /** - * Test get autolinks. - * - * @throws Exception - * the exception - */ - @Test - public void testListAllAutolinks() throws Exception { - assertThat("Initial autolinks list", repo.listAutolinks().toList(), is(empty())); - - GHAutolink autolink1 = repo.createAutolink() - .withKeyPrefix("LIST-") - .withUrlTemplate("https://example.com/list1/") - .withIsAlphanumeric(true) - .create(); - - GHAutolink autolink2 = repo.createAutolink() - .withKeyPrefix("LISTED-") - .withUrlTemplate("https://example.com/list2/") - .withIsAlphanumeric(false) - .create(); - - boolean found1 = false; - boolean found2 = false; - - PagedIterable autolinks = repo.listAutolinks(); - - List autolinkList = autolinks.toList(); - assertThat("Number of autolinks", autolinkList.size(), is(2)); - - for (GHAutolink autolink : autolinkList) { - - if (autolink.getId() == autolink1.getId()) { - found1 = true; - assertThat(autolink.getKeyPrefix(), equalTo(autolink1.getKeyPrefix())); - assertThat(autolink.getUrlTemplate(), equalTo(autolink1.getUrlTemplate())); - assertThat(autolink.isAlphanumeric(), equalTo(autolink1.isAlphanumeric())); - } - if (autolink.getId() == autolink2.getId()) { - found2 = true; - assertThat(autolink.getKeyPrefix(), equalTo(autolink2.getKeyPrefix())); - assertThat(autolink.getUrlTemplate(), equalTo(autolink2.getUrlTemplate())); - assertThat(autolink.isAlphanumeric(), equalTo(autolink2.isAlphanumeric())); - } - } - - assertThat("First autolink", found1, is(true)); - assertThat("Second autolink", found2, is(true)); - - } - - /** - * Test get autolink. - * - * @throws Exception - * the exception - */ - @Test - public void testReadAutolink() throws Exception { - GHAutolink autolink = repo.createAutolink() - .withKeyPrefix("JIRA-") - .withUrlTemplate("https://example.com/test/") - .withIsAlphanumeric(false) - .create(); - - GHAutolink fetched = repo.readAutolink(autolink.getId()); - - assertThat(fetched.getId(), equalTo(autolink.getId())); - assertThat(fetched.getKeyPrefix(), equalTo(autolink.getKeyPrefix())); - assertThat(fetched.getUrlTemplate(), equalTo(autolink.getUrlTemplate())); - assertThat(fetched.isAlphanumeric(), equalTo(autolink.isAlphanumeric())); - assertThat(fetched.getOwner(), equalTo(repo)); - - autolink.delete(); - - } -} diff --git a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java index 5418427bf5..d01ecabcf7 100755 --- a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java +++ b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java @@ -23,19 +23,19 @@ */ public class GHBranchProtectionTest extends AbstractGitHubWireMockTest { - private static final String BRANCH = "main"; - - private static final String BRANCH_REF = "heads/" + BRANCH; - private GHBranch branch; - - private GHRepository repo; - /** * Create default GHBranchProtectionTest instance */ public GHBranchProtectionTest() { } + private static final String BRANCH = "main"; + private static final String BRANCH_REF = "heads/" + BRANCH; + + private GHBranch branch; + + private GHRepository repo; + /** * Sets the up. * @@ -48,45 +48,6 @@ public void setUp() throws Exception { branch = repo.getBranch(BRANCH); } - /** - * Checks with app ids are being populated - * - * @throws Exception - * the exception - */ - @Test - public void testChecksWithAppIds() throws Exception { - GHBranchProtection protection = branch.enableProtection() - .addRequiredChecks(new GHBranchProtection.Check("context", -1), - new GHBranchProtection.Check("context2", 123), - new GHBranchProtection.Check("context3", null)) - .enable(); - - ArrayList resultChecks = new ArrayList<>( - protection.getRequiredStatusChecks().getChecks()); - - assertThat(resultChecks.size(), is(3)); - assertThat(resultChecks.get(0).getContext(), is("context")); - assertThat(resultChecks.get(0).getAppId(), nullValue()); - assertThat(resultChecks.get(1).getContext(), is("context2")); - assertThat(resultChecks.get(1).getAppId(), is(123)); - assertThat(resultChecks.get(2).getContext(), is("context3")); - } - - /** - * Test disable protection only. - * - * @throws Exception - * the exception - */ - @Test - public void testDisableProtectionOnly() throws Exception { - GHBranchProtection protection = branch.enableProtection().enable(); - assertThat(repo.getBranch(BRANCH).isProtected(), is(true)); - branch.disableProtection(); - assertThat(repo.getBranch(BRANCH).isProtected(), is(false)); - } - /** * Test enable branch protections. * @@ -120,6 +81,52 @@ public void testEnableBranchProtections() throws Exception { verifyBranchProtection(protection); } + private void verifyBranchProtection(GHBranchProtection protection) { + RequiredStatusChecks statusChecks = protection.getRequiredStatusChecks(); + assertThat(statusChecks, notNullValue()); + assertThat(statusChecks.isRequiresBranchUpToDate(), is(true)); + assertThat(statusChecks.getContexts(), contains("test-status-check")); + + RequiredReviews requiredReviews = protection.getRequiredReviews(); + assertThat(requiredReviews, notNullValue()); + assertThat(requiredReviews.isDismissStaleReviews(), is(true)); + assertThat(requiredReviews.isRequireCodeOwnerReviews(), is(true)); + assertThat(requiredReviews.isRequireLastPushApproval(), is(true)); + assertThat(requiredReviews.getRequiredReviewers(), equalTo(2)); + + AllowDeletions allowDeletions = protection.getAllowDeletions(); + assertThat(allowDeletions, notNullValue()); + assertThat(allowDeletions.isEnabled(), is(true)); + + AllowForcePushes allowForcePushes = protection.getAllowForcePushes(); + assertThat(allowForcePushes, notNullValue()); + assertThat(allowForcePushes.isEnabled(), is(true)); + + AllowForkSyncing allowForkSyncing = protection.getAllowForkSyncing(); + assertThat(allowForkSyncing, notNullValue()); + assertThat(allowForkSyncing.isEnabled(), is(true)); + + BlockCreations blockCreations = protection.getBlockCreations(); + assertThat(blockCreations, notNullValue()); + assertThat(blockCreations.isEnabled(), is(true)); + + EnforceAdmins enforceAdmins = protection.getEnforceAdmins(); + assertThat(enforceAdmins, notNullValue()); + assertThat(enforceAdmins.isEnabled(), is(true)); + + LockBranch lockBranch = protection.getLockBranch(); + assertThat(lockBranch, notNullValue()); + assertThat(lockBranch.isEnabled(), is(true)); + + RequiredConversationResolution requiredConversationResolution = protection.getRequiredConversationResolution(); + assertThat(requiredConversationResolution, notNullValue()); + assertThat(requiredConversationResolution.isEnabled(), is(true)); + + RequiredLinearHistory requiredLinearHistory = protection.getRequiredLinearHistory(); + assertThat(requiredLinearHistory, notNullValue()); + assertThat(requiredLinearHistory.isEnabled(), is(true)); + } + /** * Test enable protection only. * @@ -132,6 +139,20 @@ public void testEnableProtectionOnly() throws Exception { assertThat(repo.getBranch(BRANCH).isProtected(), is(true)); } + /** + * Test disable protection only. + * + * @throws Exception + * the exception + */ + @Test + public void testDisableProtectionOnly() throws Exception { + GHBranchProtection protection = branch.enableProtection().enable(); + assertThat(repo.getBranch(BRANCH).isProtected(), is(true)); + branch.disableProtection(); + assertThat(repo.getBranch(BRANCH).isProtected(), is(false)); + } + /** * Test enable require reviews only. * @@ -158,21 +179,6 @@ public void testEnableRequireReviewsOnly() throws Exception { assertThat(protection.getRequiredReviews().getRequiredReviewers(), equalTo(1)); } - /** - * Test get protection. - * - * @throws Exception - * the exception - */ - @Test - public void testGetProtection() throws Exception { - GHBranchProtection protection = branch.enableProtection().enable(); - GHBranchProtection protectionTest = repo.getBranch(BRANCH).getProtection(); - Boolean condition = protectionTest instanceof GHBranchProtection; - assertThat(protectionTest, instanceOf(GHBranchProtection.class)); - assertThat(repo.getBranch(BRANCH).isProtected(), is(true)); - } - /** * Test signed commits. * @@ -192,49 +198,43 @@ public void testSignedCommits() throws Exception { assertThat(protection.getRequiredSignatures(), is(false)); } - private void verifyBranchProtection(GHBranchProtection protection) { - RequiredStatusChecks statusChecks = protection.getRequiredStatusChecks(); - assertThat(statusChecks, notNullValue()); - assertThat(statusChecks.isRequiresBranchUpToDate(), is(true)); - assertThat(statusChecks.getContexts(), contains("test-status-check")); - - RequiredReviews requiredReviews = protection.getRequiredReviews(); - assertThat(requiredReviews, notNullValue()); - assertThat(requiredReviews.isDismissStaleReviews(), is(true)); - assertThat(requiredReviews.isRequireCodeOwnerReviews(), is(true)); - assertThat(requiredReviews.isRequireLastPushApproval(), is(true)); - assertThat(requiredReviews.getRequiredReviewers(), equalTo(2)); - - AllowDeletions allowDeletions = protection.getAllowDeletions(); - assertThat(allowDeletions, notNullValue()); - assertThat(allowDeletions.isEnabled(), is(true)); - - AllowForcePushes allowForcePushes = protection.getAllowForcePushes(); - assertThat(allowForcePushes, notNullValue()); - assertThat(allowForcePushes.isEnabled(), is(true)); - - AllowForkSyncing allowForkSyncing = protection.getAllowForkSyncing(); - assertThat(allowForkSyncing, notNullValue()); - assertThat(allowForkSyncing.isEnabled(), is(true)); - - BlockCreations blockCreations = protection.getBlockCreations(); - assertThat(blockCreations, notNullValue()); - assertThat(blockCreations.isEnabled(), is(true)); - - EnforceAdmins enforceAdmins = protection.getEnforceAdmins(); - assertThat(enforceAdmins, notNullValue()); - assertThat(enforceAdmins.isEnabled(), is(true)); + /** + * Checks with app ids are being populated + * + * @throws Exception + * the exception + */ + @Test + public void testChecksWithAppIds() throws Exception { + GHBranchProtection protection = branch.enableProtection() + .addRequiredChecks(new GHBranchProtection.Check("context", -1), + new GHBranchProtection.Check("context2", 123), + new GHBranchProtection.Check("context3", null)) + .enable(); - LockBranch lockBranch = protection.getLockBranch(); - assertThat(lockBranch, notNullValue()); - assertThat(lockBranch.isEnabled(), is(true)); + ArrayList resultChecks = new ArrayList<>( + protection.getRequiredStatusChecks().getChecks()); - RequiredConversationResolution requiredConversationResolution = protection.getRequiredConversationResolution(); - assertThat(requiredConversationResolution, notNullValue()); - assertThat(requiredConversationResolution.isEnabled(), is(true)); + assertThat(resultChecks.size(), is(3)); + assertThat(resultChecks.get(0).getContext(), is("context")); + assertThat(resultChecks.get(0).getAppId(), nullValue()); + assertThat(resultChecks.get(1).getContext(), is("context2")); + assertThat(resultChecks.get(1).getAppId(), is(123)); + assertThat(resultChecks.get(2).getContext(), is("context3")); + } - RequiredLinearHistory requiredLinearHistory = protection.getRequiredLinearHistory(); - assertThat(requiredLinearHistory, notNullValue()); - assertThat(requiredLinearHistory.isEnabled(), is(true)); + /** + * Test get protection. + * + * @throws Exception + * the exception + */ + @Test + public void testGetProtection() throws Exception { + GHBranchProtection protection = branch.enableProtection().enable(); + GHBranchProtection protectionTest = repo.getBranch(BRANCH).getProtection(); + Boolean condition = protectionTest instanceof GHBranchProtection; + assertThat(protectionTest, instanceOf(GHBranchProtection.class)); + assertThat(repo.getBranch(BRANCH).isProtected(), is(true)); } } diff --git a/src/test/java/org/kohsuke/github/GHBranchTest.java b/src/test/java/org/kohsuke/github/GHBranchTest.java index e74a402d94..117da049f7 100644 --- a/src/test/java/org/kohsuke/github/GHBranchTest.java +++ b/src/test/java/org/kohsuke/github/GHBranchTest.java @@ -10,17 +10,17 @@ */ public class GHBranchTest extends AbstractGitHubWireMockTest { - private static final String BRANCH_1 = "testBranch1"; - - private static final String BRANCH_2 = "testBranch2"; - private GHRepository repository; - /** * Create default GHBranchTest instance */ public GHBranchTest() { } + private static final String BRANCH_1 = "testBranch1"; + private static final String BRANCH_2 = "testBranch2"; + + private GHRepository repository; + /** * Test merge branch. * diff --git a/src/test/java/org/kohsuke/github/GHCheckRunBuilderTest.java b/src/test/java/org/kohsuke/github/GHCheckRunBuilderTest.java index ef888faf5e..a52e07e3a4 100644 --- a/src/test/java/org/kohsuke/github/GHCheckRunBuilderTest.java +++ b/src/test/java/org/kohsuke/github/GHCheckRunBuilderTest.java @@ -29,7 +29,6 @@ import org.kohsuke.github.GHCheckRun.Status; import java.io.IOException; -import java.time.Instant; import java.util.Date; import static org.hamcrest.Matchers.*; @@ -47,6 +46,17 @@ public class GHCheckRunBuilderTest extends AbstractGHAppInstallationTest { public GHCheckRunBuilderTest() { } + /** + * Gets the installation github. + * + * @return the installation github + * @throws IOException + * Signals that an I/O exception has occurred. + */ + protected GitHub getInstallationGithub() throws IOException { + return getAppInstallationWithToken(jwtProvider3.getEncodedAuthorization()).root(); + } + /** * Creates the check run. * @@ -79,28 +89,6 @@ public void createCheckRun() throws Exception { assertThat(checkRun.getOutput().getText(), equalTo("Hello Text!")); } - /** - * Creates the check run err missing conclusion. - * - * @throws Exception - * the exception - */ - @Test - public void createCheckRunErrMissingConclusion() throws Exception { - try { - getInstallationGithub().getRepository("hub4j-test-org/test-checks") - .createCheckRun("outstanding", "89a9ae301e35e667756034fdc933b1fc94f63fc1") - .withStatus(GHCheckRun.Status.COMPLETED) - .create(); - fail("should have been rejected"); - } catch (HttpException x) { - assertThat(x.getResponseCode(), equalTo(422)); - assertThat(x.getMessage(), containsString("\\\"conclusion\\\" wasn't supplied")); - assertThat(x.getUrl(), containsString("/repos/hub4j-test-org/test-checks/check-runs")); - assertThat(x.getResponseMessage(), containsString("Unprocessable Entity")); - } - } - /** * Creates the check run many annotations. * @@ -164,6 +152,28 @@ public void createPendingCheckRun() throws Exception { assertThat(checkRun.getId(), equalTo(1424883451L)); } + /** + * Creates the check run err missing conclusion. + * + * @throws Exception + * the exception + */ + @Test + public void createCheckRunErrMissingConclusion() throws Exception { + try { + getInstallationGithub().getRepository("hub4j-test-org/test-checks") + .createCheckRun("outstanding", "89a9ae301e35e667756034fdc933b1fc94f63fc1") + .withStatus(GHCheckRun.Status.COMPLETED) + .create(); + fail("should have been rejected"); + } catch (HttpException x) { + assertThat(x.getResponseCode(), equalTo(422)); + assertThat(x.getMessage(), containsString("\\\"conclusion\\\" wasn't supplied")); + assertThat(x.getUrl(), containsString("/repos/hub4j-test-org/test-checks/check-runs")); + assertThat(x.getResponseMessage(), containsString("Unprocessable Entity")); + } + } + /** * Update check run. * @@ -175,7 +185,7 @@ public void updateCheckRun() throws Exception { GHCheckRun checkRun = getInstallationGithub().getRepository("hub4j-test-org/test-checks") .createCheckRun("foo", "89a9ae301e35e667756034fdc933b1fc94f63fc1") .withStatus(GHCheckRun.Status.IN_PROGRESS) - .withStartedAt(Instant.ofEpochMilli(999_999_000)) + .withStartedAt(new Date(999_999_000)) .add(new GHCheckRunBuilder.Output("Some Title", "what happened…") .add(new GHCheckRunBuilder.Annotation("stuff.txt", 1, @@ -187,7 +197,7 @@ public void updateCheckRun() throws Exception { .withConclusion(GHCheckRun.Conclusion.SUCCESS) .withCompletedAt(new Date(999_999_999)) .create(); - assertThat(Instant.ofEpochMilli(999_999_000), equalTo(updated.getStartedAt())); + assertThat(new Date(999_999_000), equalTo(updated.getStartedAt())); assertThat("foo", equalTo(updated.getName())); assertThat(checkRun.getOutput().getAnnotationsCount(), equalTo(1)); } @@ -203,7 +213,7 @@ public void updateCheckRunWithName() throws Exception { GHCheckRun checkRun = getInstallationGithub().getRepository("hub4j-test-org/test-checks") .createCheckRun("foo", "89a9ae301e35e667756034fdc933b1fc94f63fc1") .withStatus(GHCheckRun.Status.IN_PROGRESS) - .withStartedAt(Instant.ofEpochMilli(999_999_000)) + .withStartedAt(new Date(999_999_000)) .add(new GHCheckRunBuilder.Output("Some Title", "what happened…") .add(new GHCheckRunBuilder.Annotation("stuff.txt", 1, @@ -213,10 +223,10 @@ public void updateCheckRunWithName() throws Exception { GHCheckRun updated = checkRun.update() .withStatus(GHCheckRun.Status.COMPLETED) .withConclusion(GHCheckRun.Conclusion.SUCCESS) - .withCompletedAt(Instant.ofEpochMilli(999_999_999)) + .withCompletedAt(new Date(999_999_999)) .withName("bar", checkRun.getName()) .create(); - assertThat(Instant.ofEpochMilli(999_999_000), equalTo(updated.getStartedAt())); + assertThat(new Date(999_999_000), equalTo(updated.getStartedAt())); assertThat("bar", equalTo(updated.getName())); assertThat(checkRun.getOutput().getAnnotationsCount(), equalTo(1)); } @@ -233,7 +243,7 @@ public void updateCheckRunWithNameException() throws Exception { GHCheckRun checkRun = getInstallationGithub().getRepository("hub4j-test-org/test-checks") .createCheckRun("foo", "89a9ae301e35e667756034fdc933b1fc94f63fc1") .withStatus(GHCheckRun.Status.IN_PROGRESS) - .withStartedAt(Instant.ofEpochMilli(999_999_000)) + .withStartedAt(new Date(999_999_000)) .add(new GHCheckRunBuilder.Output("Some Title", "what happened…") .add(new GHCheckRunBuilder.Annotation("stuff.txt", 1, @@ -248,15 +258,4 @@ public void updateCheckRunWithNameException() throws Exception { .withName("bar", null) .create()); } - - /** - * Gets the installation github. - * - * @return the installation github - * @throws IOException - * Signals that an I/O exception has occurred. - */ - protected GitHub getInstallationGithub() throws IOException { - return getAppInstallationWithToken(jwtProvider3.getEncodedAuthorization()).root(); - } } diff --git a/src/test/java/org/kohsuke/github/GHCodeownersErrorTest.java b/src/test/java/org/kohsuke/github/GHCodeownersErrorTest.java index 6b964c59d3..958d4908be 100644 --- a/src/test/java/org/kohsuke/github/GHCodeownersErrorTest.java +++ b/src/test/java/org/kohsuke/github/GHCodeownersErrorTest.java @@ -44,10 +44,6 @@ public void testGetCodeownersErrors() throws IOException { assertThat(firstError.getPath(), is(".github/CODEOWNERS")); } - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("github-api"); - } - /** * Gets the repository. * @@ -58,4 +54,8 @@ private GHRepository getRepository(GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("github-api"); + } } diff --git a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java index 7c60131669..36151cea4f 100644 --- a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java +++ b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java @@ -20,18 +20,18 @@ */ public class GHContentIntegrationTest extends AbstractGitHubWireMockTest { - // file name with spaces and other chars - private final String createdDirectory = "test+directory #50"; - - private final String createdFilename = createdDirectory + "/test file-to+create-#1.txt"; - - private GHRepository repo; /** * Create default GHContentIntegrationTest instance */ public GHContentIntegrationTest() { } + private GHRepository repo; + + // file name with spaces and other chars + private final String createdDirectory = "test+directory #50"; + private final String createdFilename = createdDirectory + "/test file-to+create-#1.txt"; + /** * Cleanup. * @@ -64,6 +64,88 @@ public void setUp() throws Exception { repo = gitHub.getRepository("hub4j-test-org/GHContentIntegrationTest"); } + /** + * Test get repository. + * + * @throws Exception + * the exception + */ + @Test + public void testGetRepository() throws Exception { + GHRepository testRepo = gitHub.getRepositoryById(repo.getId()); + assertThat(testRepo.getName(), equalTo(repo.getName())); + } + + /** + * Test get repository created from a template repository + * + * @throws Exception + * the exception + */ + @Test + public void testGetRepositoryWithTemplateRepositoryInfo() throws Exception { + GHRepository testRepo = gitHub.getRepositoryById(repo.getId()); + assertThat(testRepo.getTemplateRepository(), notNullValue()); + assertThat(testRepo.getTemplateRepository().getOwnerName(), equalTo("octocat")); + assertThat(testRepo.getTemplateRepository().isTemplate(), equalTo(true)); + } + + /** + * Test get file content. + * + * @throws Exception + * the exception + */ + @Test + public void testGetFileContent() throws Exception { + repo = gitHub.getRepository("hub4j-test-org/GHContentIntegrationTest"); + GHContent content = repo.getFileContent("ghcontent-ro/a-file-with-content"); + + assertThat(content.isFile(), is(true)); + assertThat(content.getContent(), equalTo("thanks for reading me\n")); + } + + /** + * Test get empty file content. + * + * @throws Exception + * the exception + */ + @Test + public void testGetEmptyFileContent() throws Exception { + GHContent content = repo.getFileContent("ghcontent-ro/an-empty-file"); + + assertThat(content.isFile(), is(true)); + assertThat(content.getContent(), is(emptyString())); + } + + /** + * Test get directory content. + * + * @throws Exception + * the exception + */ + @Test + public void testGetDirectoryContent() throws Exception { + List entries = repo.getDirectoryContent("ghcontent-ro/a-dir-with-3-entries"); + + assertThat(entries.size(), equalTo(3)); + } + + /** + * Test get directory content trailing slash. + * + * @throws Exception + * the exception + */ + @Test + public void testGetDirectoryContentTrailingSlash() throws Exception { + // Used to truncate the ?ref=main, see gh-224 https://github.com/kohsuke/github-api/pull/224 + List entries = repo.getDirectoryContent("ghcontent-ro/a-dir-with-3-entries/", "main"); + + assertThat(entries.get(0).getUrl(), endsWith("?ref=main")); + } + /** * Test CRUD content. * @@ -146,178 +228,91 @@ public void testCRUDContent() throws Exception { } /** - * Test get directory content. + * Check created commits. * + * @param gitCommit + * the git commit + * @param ghCommit + * the gh commit + * @param expectedRequestCount + * the expected request count + * @return the int * @throws Exception * the exception */ - @Test - public void testGetDirectoryContent() throws Exception { - List entries = repo.getDirectoryContent("ghcontent-ro/a-dir-with-3-entries"); + int checkCreatedCommits(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) throws Exception { + expectedRequestCount = checkBasicCommitInfo(gitCommit, ghCommit, expectedRequestCount); + assertThat(mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - assertThat(entries.size(), equalTo(3)); - } + assertThat(gitCommit.getMessage(), equalTo("Creating a file for integration tests.")); + assertThat(gitCommit.getAuthoredDate(), equalTo(GitHubClient.parseDate("2021-06-28T20:37:49Z"))); + assertThat(gitCommit.getCommitDate(), equalTo(GitHubClient.parseDate("2021-06-28T20:37:49Z"))); - /** - * Test get directory content trailing slash. - * - * @throws Exception - * the exception - */ - @Test - public void testGetDirectoryContentTrailingSlash() throws Exception { - // Used to truncate the ?ref=main, see gh-224 https://github.com/kohsuke/github-api/pull/224 - List entries = repo.getDirectoryContent("ghcontent-ro/a-dir-with-3-entries/", "main"); + assertThat(ghCommit.getCommitShortInfo().getMessage(), equalTo("Creating a file for integration tests.")); + assertThat("Message already resolved", mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); + assertThrows(GHException.class, () -> ghCommit.getCommitShortInfo().getCommentCount()); - assertThat(entries.get(0).getUrl(), endsWith("?ref=main")); - } + ghCommit.populate(); + assertThat("Populate GHCommit", mockGitHub.getRequestCount(), equalTo(expectedRequestCount += 1)); - /** - * Test get empty file content. - * - * @throws Exception - * the exception - */ - @Test - public void testGetEmptyFileContent() throws Exception { - GHContent content = repo.getFileContent("ghcontent-ro/an-empty-file"); + expectedRequestCount = checkCommitUserInfo(gitCommit, ghCommit, expectedRequestCount); + assertThat("Resolved GHUser for GHCommit", mockGitHub.getRequestCount(), equalTo(expectedRequestCount += 1)); - assertThat(content.isFile(), is(true)); - assertThat(content.getContent(), is(emptyString())); - } + expectedRequestCount = checkCommitTree(gitCommit, ghCommit, expectedRequestCount); - /** - * Test get file content. - * - * @throws Exception - * the exception - */ - @Test - public void testGetFileContent() throws Exception { - repo = gitHub.getRepository("hub4j-test-org/GHContentIntegrationTest"); - GHContent content = repo.getFileContent("ghcontent-ro/a-file-with-content"); + expectedRequestCount = checkCommitParents(gitCommit, ghCommit, expectedRequestCount); - assertThat(content.isFile(), is(true)); - assertThat(content.getContent(), equalTo("thanks for reading me\n")); + return expectedRequestCount; } /** - * Test get file content with non ascii path. + * Gets the GH commit. * + * @param resp + * the resp + * @return the GH commit * @throws Exception * the exception */ - @Test - public void testGetFileContentWithNonAsciiPath() throws Exception { - final GHRepository repo = gitHub.getRepository("hub4j-test-org/GHContentIntegrationTest"); - final GHContent fileContent = repo.getFileContent("ghcontent-ro/a-file-with-\u00F6"); - assertThat(IOUtils.readLines(fileContent.read(), StandardCharsets.UTF_8), hasItems("test")); - - final GHContent fileContent2 = repo.getFileContent(fileContent.getPath()); - assertThat(IOUtils.readLines(fileContent2.read(), StandardCharsets.UTF_8), hasItems("test")); + GHCommit getGHCommit(GHContentUpdateResponse resp) throws Exception { + return resp.getCommit().toGHCommit(); } /** - * Test get file content with symlink. + * Check updated content response commits. * + * @param gitCommit + * the git commit + * @param ghCommit + * the gh commit + * @param expectedRequestCount + * the expected request count + * @return the int * @throws Exception * the exception */ - @Test - public void testGetFileContentWithSymlink() throws Exception { - final GHRepository repo = gitHub.getRepository("hub4j-test-org/GHContentIntegrationTest"); - - final GHContent fileContent = repo.getFileContent("ghcontent-ro/a-symlink-to-a-file"); - // for whatever reason GH says this is a file :-o - assertThat(IOUtils.toString(fileContent.read(), StandardCharsets.UTF_8), is("thanks for reading me\n")); - - final GHContent dirContent = repo.getFileContent("ghcontent-ro/a-symlink-to-a-dir"); - // but symlinks to directories are symlinks! - assertThat(dirContent, - allOf(hasProperty("target", is("a-dir-with-3-entries")), hasProperty("type", is("symlink")))); + int checkUpdatedContentResponseCommits(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) + throws Exception { - // future somehow... + expectedRequestCount = checkBasicCommitInfo(gitCommit, ghCommit, expectedRequestCount); + assertThat(mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - // final GHContent fileContent2 = repo.getFileContent("ghcontent-ro/a-symlink-to-a-dir/entry-one"); - // this needs special handling and will 404 from GitHub - // assertThat(IOUtils.toString(fileContent.read(), StandardCharsets.UTF_8), is("")); - } + assertThat(gitCommit.getMessage(), equalTo("Updated file for integration tests.")); + assertThat(gitCommit.getAuthoredDate(), equalTo(GitHubClient.parseDate("2021-06-28T20:37:51Z"))); + assertThat(gitCommit.getCommitDate(), equalTo(GitHubClient.parseDate("2021-06-28T20:37:51Z"))); - /** - * Test get repository. - * - * @throws Exception - * the exception - */ - @Test - public void testGetRepository() throws Exception { - GHRepository testRepo = gitHub.getRepositoryById(repo.getId()); - assertThat(testRepo.getName(), equalTo(repo.getName())); - } + assertThat(ghCommit.getCommitShortInfo().getMessage(), equalTo("Updated file for integration tests.")); + assertThat("Message already resolved", mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - /** - * Test get repository created from a template repository - * - * @throws Exception - * the exception - */ - @Test - public void testGetRepositoryWithTemplateRepositoryInfo() throws Exception { - GHRepository testRepo = gitHub.getRepositoryById(repo.getId()); - assertThat(testRepo.getTemplateRepository(), notNullValue()); - assertThat(testRepo.getTemplateRepository().getOwnerName(), equalTo("octocat")); - assertThat(testRepo.getTemplateRepository().isTemplate(), equalTo(true)); - } + ghCommit.populate(); + assertThat("Populate GHCommit", mockGitHub.getRequestCount(), equalTo(expectedRequestCount += 1)); - /** - * Test MIME long. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testMIMELong() throws IOException { - GHRepository ghRepository = getTempRepository(); - GHContentBuilder ghContentBuilder = ghRepository.createContent(); - ghContentBuilder.message("Some commit msg"); - ghContentBuilder.path("MIME-Long.md"); - ghContentBuilder.content("1234567890123456789012345678901234567890123456789012345678"); - ghContentBuilder.commit(); - } + expectedRequestCount = checkCommitUserInfo(gitCommit, ghCommit, expectedRequestCount); + assertThat("GHUser already resolved", mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - /** - * Test MIME longer. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testMIMELonger() throws IOException { - GHRepository ghRepository = getTempRepository(); - GHContentBuilder ghContentBuilder = ghRepository.createContent(); - ghContentBuilder.message("Some commit msg"); - ghContentBuilder.path("MIME-Long.md"); - ghContentBuilder.content("123456789012345678901234567890123456789012345678901234567890" - + "123456789012345678901234567890123456789012345678901234567890" - + "123456789012345678901234567890123456789012345678901234567890" - + "123456789012345678901234567890123456789012345678901234567890"); - ghContentBuilder.commit(); - } + expectedRequestCount = checkCommitTree(gitCommit, ghCommit, expectedRequestCount); - /** - * Test MIME small. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testMIMESmall() throws IOException { - GHRepository ghRepository = getTempRepository(); - GHContentBuilder ghContentBuilder = ghRepository.createContent(); - ghContentBuilder.message("Some commit msg"); - ghContentBuilder.path("MIME-Small.md"); - ghContentBuilder.content("123456789012345678901234567890123456789012345678901234567"); - ghContentBuilder.commit(); + return expectedRequestCount; } /** @@ -330,8 +325,10 @@ public void testMIMESmall() throws IOException { * @param expectedRequestCount * the expected request count * @return the int + * @throws IOException + * Signals that an I/O exception has occurred. */ - int checkBasicCommitInfo(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) { + int checkBasicCommitInfo(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) throws IOException { assertThat(gitCommit, notNullValue()); assertThat(gitCommit.getSHA1(), notNullValue()); assertThat(gitCommit.getUrl().toString(), @@ -349,7 +346,7 @@ int checkBasicCommitInfo(GitCommit gitCommit, GHCommit ghCommit, int expectedReq } /** - * Check commit parents. + * Check commit user info. * * @param gitCommit * the git commit @@ -358,20 +355,27 @@ int checkBasicCommitInfo(GitCommit gitCommit, GHCommit ghCommit, int expectedReq * @param expectedRequestCount * the expected request count * @return the int + * @throws Exception + * the exception */ - int checkCommitParents(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) { - assertThat(gitCommit.getParentSHA1s().size(), is(greaterThan(0))); - assertThat(gitCommit.getParentSHA1s().get(0), notNullValue()); - assertThat(ghCommit.getParentSHA1s().size(), is(greaterThan(0))); - assertThat(ghCommit.getParentSHA1s().get(0), notNullValue()); + int checkCommitUserInfo(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) throws Exception { + assertThat(gitCommit.getAuthor().getName(), equalTo("Liam Newman")); + assertThat(gitCommit.getAuthor().getEmail(), equalTo("bitwiseman@gmail.com")); - return expectedRequestCount; - } + assertThat(gitCommit.getAuthor().getName(), equalTo("Liam Newman")); + assertThat(gitCommit.getAuthor().getEmail(), equalTo("bitwiseman@gmail.com")); + assertThat(gitCommit.getCommitter().getName(), equalTo("Liam Newman")); + assertThat(gitCommit.getCommitter().getEmail(), equalTo("bitwiseman@gmail.com")); + assertThat("GHUser already resolved", mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - // @Test - // public void testGitCommit2GHCommitExceptions() { + assertThat(ghCommit.getAuthor().getName(), equalTo("Liam Newman")); + assertThat(ghCommit.getAuthor().getEmail(), equalTo("bitwiseman@gmail.com")); - // } + assertThat(ghCommit.getCommitter().getName(), equalTo("Liam Newman")); + assertThat(ghCommit.getCommitter().getEmail(), equalTo("bitwiseman@gmail.com")); + + return expectedRequestCount; + } /** * Check commit tree. @@ -404,7 +408,7 @@ int checkCommitTree(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestC } /** - * Check commit user info. + * Check commit parents. * * @param gitCommit * the git commit @@ -413,112 +417,114 @@ int checkCommitTree(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestC * @param expectedRequestCount * the expected request count * @return the int - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ - int checkCommitUserInfo(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) throws Exception { - assertThat(gitCommit.getAuthor().getName(), equalTo("Liam Newman")); - assertThat(gitCommit.getAuthor().getEmail(), equalTo("bitwiseman@gmail.com")); + int checkCommitParents(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) throws IOException { + assertThat(gitCommit.getParentSHA1s().size(), is(greaterThan(0))); + assertThat(gitCommit.getParentSHA1s().get(0), notNullValue()); + assertThat(ghCommit.getParentSHA1s().size(), is(greaterThan(0))); + assertThat(ghCommit.getParentSHA1s().get(0), notNullValue()); - assertThat(gitCommit.getAuthor().getName(), equalTo("Liam Newman")); - assertThat(gitCommit.getAuthor().getEmail(), equalTo("bitwiseman@gmail.com")); - assertThat(gitCommit.getCommitter().getName(), equalTo("Liam Newman")); - assertThat(gitCommit.getCommitter().getEmail(), equalTo("bitwiseman@gmail.com")); - assertThat("GHUser already resolved", mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); + return expectedRequestCount; + } - assertThat(ghCommit.getAuthor().getName(), equalTo("Liam Newman")); - assertThat(ghCommit.getAuthor().getEmail(), equalTo("bitwiseman@gmail.com")); + // @Test + // public void testGitCommit2GHCommitExceptions() { - assertThat(ghCommit.getCommitter().getName(), equalTo("Liam Newman")); - assertThat(ghCommit.getCommitter().getEmail(), equalTo("bitwiseman@gmail.com")); + // } - return expectedRequestCount; + /** + * Test MIME small. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testMIMESmall() throws IOException { + GHRepository ghRepository = getTempRepository(); + GHContentBuilder ghContentBuilder = ghRepository.createContent(); + ghContentBuilder.message("Some commit msg"); + ghContentBuilder.path("MIME-Small.md"); + ghContentBuilder.content("123456789012345678901234567890123456789012345678901234567"); + ghContentBuilder.commit(); } /** - * Check created commits. + * Test MIME long. * - * @param gitCommit - * the git commit - * @param ghCommit - * the gh commit - * @param expectedRequestCount - * the expected request count - * @return the int - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ - int checkCreatedCommits(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) throws Exception { - expectedRequestCount = checkBasicCommitInfo(gitCommit, ghCommit, expectedRequestCount); - assertThat(mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - - assertThat(gitCommit.getMessage(), equalTo("Creating a file for integration tests.")); - assertThat(gitCommit.getAuthoredDate(), equalTo(GitHubClient.parseInstant("2021-06-28T20:37:49Z"))); - assertThat(gitCommit.getCommitDate(), equalTo(GitHubClient.parseInstant("2021-06-28T20:37:49Z"))); - - assertThat(ghCommit.getCommitShortInfo().getMessage(), equalTo("Creating a file for integration tests.")); - assertThat("Message already resolved", mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - assertThrows(GHException.class, () -> ghCommit.getCommitShortInfo().getCommentCount()); - - ghCommit.populate(); - assertThat("Populate GHCommit", mockGitHub.getRequestCount(), equalTo(expectedRequestCount += 1)); - - expectedRequestCount = checkCommitUserInfo(gitCommit, ghCommit, expectedRequestCount); - assertThat("Resolved GHUser for GHCommit", mockGitHub.getRequestCount(), equalTo(expectedRequestCount += 1)); - - expectedRequestCount = checkCommitTree(gitCommit, ghCommit, expectedRequestCount); - - expectedRequestCount = checkCommitParents(gitCommit, ghCommit, expectedRequestCount); + @Test + public void testMIMELong() throws IOException { + GHRepository ghRepository = getTempRepository(); + GHContentBuilder ghContentBuilder = ghRepository.createContent(); + ghContentBuilder.message("Some commit msg"); + ghContentBuilder.path("MIME-Long.md"); + ghContentBuilder.content("1234567890123456789012345678901234567890123456789012345678"); + ghContentBuilder.commit(); + } - return expectedRequestCount; + /** + * Test MIME longer. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testMIMELonger() throws IOException { + GHRepository ghRepository = getTempRepository(); + GHContentBuilder ghContentBuilder = ghRepository.createContent(); + ghContentBuilder.message("Some commit msg"); + ghContentBuilder.path("MIME-Long.md"); + ghContentBuilder.content("123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890" + + "123456789012345678901234567890123456789012345678901234567890"); + ghContentBuilder.commit(); } /** - * Check updated content response commits. + * Test get file content with non ascii path. * - * @param gitCommit - * the git commit - * @param ghCommit - * the gh commit - * @param expectedRequestCount - * the expected request count - * @return the int * @throws Exception * the exception */ - int checkUpdatedContentResponseCommits(GitCommit gitCommit, GHCommit ghCommit, int expectedRequestCount) - throws Exception { - - expectedRequestCount = checkBasicCommitInfo(gitCommit, ghCommit, expectedRequestCount); - assertThat(mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - - assertThat(gitCommit.getMessage(), equalTo("Updated file for integration tests.")); - assertThat(gitCommit.getAuthoredDate(), equalTo(GitHubClient.parseInstant("2021-06-28T20:37:51Z"))); - assertThat(gitCommit.getCommitDate(), equalTo(GitHubClient.parseInstant("2021-06-28T20:37:51Z"))); - - assertThat(ghCommit.getCommitShortInfo().getMessage(), equalTo("Updated file for integration tests.")); - assertThat("Message already resolved", mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - - ghCommit.populate(); - assertThat("Populate GHCommit", mockGitHub.getRequestCount(), equalTo(expectedRequestCount += 1)); - - expectedRequestCount = checkCommitUserInfo(gitCommit, ghCommit, expectedRequestCount); - assertThat("GHUser already resolved", mockGitHub.getRequestCount(), equalTo(expectedRequestCount)); - - expectedRequestCount = checkCommitTree(gitCommit, ghCommit, expectedRequestCount); + @Test + public void testGetFileContentWithNonAsciiPath() throws Exception { + final GHRepository repo = gitHub.getRepository("hub4j-test-org/GHContentIntegrationTest"); + final GHContent fileContent = repo.getFileContent("ghcontent-ro/a-file-with-\u00F6"); + assertThat(IOUtils.readLines(fileContent.read(), StandardCharsets.UTF_8), hasItems("test")); - return expectedRequestCount; + final GHContent fileContent2 = repo.getFileContent(fileContent.getPath()); + assertThat(IOUtils.readLines(fileContent2.read(), StandardCharsets.UTF_8), hasItems("test")); } /** - * Gets the GH commit. + * Test get file content with symlink. * - * @param resp - * the resp - * @return the GH commit + * @throws Exception + * the exception */ - GHCommit getGHCommit(GHContentUpdateResponse resp) { - return resp.getCommit().toGHCommit(); + @Test + public void testGetFileContentWithSymlink() throws Exception { + final GHRepository repo = gitHub.getRepository("hub4j-test-org/GHContentIntegrationTest"); + + final GHContent fileContent = repo.getFileContent("ghcontent-ro/a-symlink-to-a-file"); + // for whatever reason GH says this is a file :-o + assertThat(IOUtils.toString(fileContent.read(), StandardCharsets.UTF_8), is("thanks for reading me\n")); + + final GHContent dirContent = repo.getFileContent("ghcontent-ro/a-symlink-to-a-dir"); + // but symlinks to directories are symlinks! + assertThat(dirContent, + allOf(hasProperty("target", is("a-dir-with-3-entries")), hasProperty("type", is("symlink")))); + + // future somehow... + + // final GHContent fileContent2 = repo.getFileContent("ghcontent-ro/a-symlink-to-a-dir/entry-one"); + // this needs special handling and will 404 from GitHub + // assertThat(IOUtils.toString(fileContent.read(), StandardCharsets.UTF_8), is("")); } } diff --git a/src/test/java/org/kohsuke/github/GHDeployKeyTest.java b/src/test/java/org/kohsuke/github/GHDeployKeyTest.java index 19918e2130..bc3bb229ab 100644 --- a/src/test/java/org/kohsuke/github/GHDeployKeyTest.java +++ b/src/test/java/org/kohsuke/github/GHDeployKeyTest.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.time.Instant; +import java.util.Date; import java.util.List; import java.util.Optional; @@ -17,17 +18,17 @@ */ public class GHDeployKeyTest extends AbstractGitHubWireMockTest { - private static final String DEPLOY_KEY_TEST_REPO_NAME = "hub4j-test-org/GHDeployKeyTest"; - - private static final String ED_25519_READONLY = "DeployKey - ed25519 - readonly"; - private static final String KEY_CREATOR_USERNAME = "van-vliet"; - private static final String RSA_4096_READWRITE = "Deploykey - rsa4096 - readwrite"; /** * Create default GHDeployKeyTest instance */ public GHDeployKeyTest() { } + private static final String DEPLOY_KEY_TEST_REPO_NAME = "hub4j-test-org/GHDeployKeyTest"; + private static final String ED_25519_READONLY = "DeployKey - ed25519 - readonly"; + private static final String RSA_4096_READWRITE = "Deploykey - rsa4096 - readwrite"; + private static final String KEY_CREATOR_USERNAME = "van-vliet"; + /** * Test get deploymentkeys. * @@ -46,13 +47,13 @@ public void testGetDeployKeys() throws IOException { assertThat("The key exists", ed25519Key, isPresent()); assertThat("The key was created at the specified date", ed25519Key.get().getCreatedAt(), - is(Instant.parse("2023-02-08T10:00:15.00Z"))); + is(Date.from(Instant.parse("2023-02-08T10:00:15.00Z")))); assertThat("The key is created by " + KEY_CREATOR_USERNAME, ed25519Key.get().getAdded_by(), is(KEY_CREATOR_USERNAME)); assertThat("The key has a last_used value", ed25519Key.get().getLastUsedAt(), - is(Instant.parse("2023-02-08T10:02:11.00Z"))); + is(Date.from(Instant.parse("2023-02-08T10:02:11.00Z")))); assertThat("The key only has read access", ed25519Key.get().isRead_only(), is(true)); assertThat("Object has a toString()", ed25519Key.get().toString(), is(notNullValue())); @@ -62,7 +63,7 @@ public void testGetDeployKeys() throws IOException { assertThat("The key exists", rsa_4096Key, isPresent()); assertThat("The key was created at the specified date", rsa_4096Key.get().getCreatedAt(), - is(Instant.parse("2023-01-26T14:12:12.00Z"))); + is(Date.from(Instant.parse("2023-01-26T14:12:12.00Z")))); assertThat("The key is created by " + KEY_CREATOR_USERNAME, rsa_4096Key.get().getAdded_by(), is(KEY_CREATOR_USERNAME)); @@ -70,10 +71,6 @@ public void testGetDeployKeys() throws IOException { assertThat("The key only has read/write access", rsa_4096Key.get().isRead_only(), is(false)); } - private GHRepository getRepository(final GitHub gitHub) throws IOException { - return gitHub.getRepository(DEPLOY_KEY_TEST_REPO_NAME); - } - /** * Gets the repository. * @@ -84,4 +81,8 @@ private GHRepository getRepository(final GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(final GitHub gitHub) throws IOException { + return gitHub.getRepository(DEPLOY_KEY_TEST_REPO_NAME); + } } diff --git a/src/test/java/org/kohsuke/github/GHDeploymentTest.java b/src/test/java/org/kohsuke/github/GHDeploymentTest.java index 32e588bcc8..56d8caa634 100644 --- a/src/test/java/org/kohsuke/github/GHDeploymentTest.java +++ b/src/test/java/org/kohsuke/github/GHDeploymentTest.java @@ -23,60 +23,53 @@ public GHDeploymentTest() { } /** - * Test get deployment by id object payload. + * Test get deployment by id string payload. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetDeploymentByIdObjectPayload() throws IOException { + public void testGetDeploymentByIdStringPayload() throws IOException { final GHRepository repo = getRepository(); final GHDeployment deployment = repo.getDeployment(178653229); assertThat(deployment, notNullValue()); assertThat(deployment.getId(), equalTo(178653229L)); assertThat(deployment.getEnvironment(), equalTo("production")); + assertThat(deployment.getPayload(), equalTo("custom")); + assertThat(deployment.getPayloadObject(), equalTo("custom")); assertThat(deployment.getRef(), equalTo("main")); assertThat(deployment.getSha(), equalTo("3a09d2de4a9a1322a0ba2c3e2f54a919ca8fe353")); assertThat(deployment.getTask(), equalTo("deploy")); - final Map payload = deployment.getPayloadMap(); - assertThat(payload.size(), equalTo(4)); - assertThat(payload.get("custom1"), equalTo(1)); - assertThat(payload.get("custom2"), equalTo("two")); - assertThat(payload.get("custom3"), equalTo(Arrays.asList("3", 3, "three"))); - assertThat(payload.get("custom4"), nullValue()); assertThat(deployment.getOriginalEnvironment(), equalTo("production")); assertThat(deployment.isProductionEnvironment(), equalTo(false)); assertThat(deployment.isTransientEnvironment(), equalTo(true)); } /** - * Test get deployment by id string payload. + * Test get deployment by id object payload. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetDeploymentByIdStringPayload() throws IOException { + public void testGetDeploymentByIdObjectPayload() throws IOException { final GHRepository repo = getRepository(); final GHDeployment deployment = repo.getDeployment(178653229); assertThat(deployment, notNullValue()); assertThat(deployment.getId(), equalTo(178653229L)); assertThat(deployment.getEnvironment(), equalTo("production")); - assertThat(deployment.getPayload(), equalTo("custom")); - assertThat(deployment.getPayloadObject(), equalTo("custom")); assertThat(deployment.getRef(), equalTo("main")); assertThat(deployment.getSha(), equalTo("3a09d2de4a9a1322a0ba2c3e2f54a919ca8fe353")); assertThat(deployment.getTask(), equalTo("deploy")); + final Map payload = deployment.getPayloadMap(); + assertThat(payload.size(), equalTo(4)); + assertThat(payload.get("custom1"), equalTo(1)); + assertThat(payload.get("custom2"), equalTo("two")); + assertThat(payload.get("custom3"), equalTo(Arrays.asList("3", 3, "three"))); + assertThat(payload.get("custom4"), nullValue()); assertThat(deployment.getOriginalEnvironment(), equalTo("production")); assertThat(deployment.isProductionEnvironment(), equalTo(false)); assertThat(deployment.isTransientEnvironment(), equalTo(true)); - assertThat(deployment.getStatusesUrl().toString(), - endsWith("/repos/hub4j-test-org/github-api/deployments/178653229/statuses")); - assertThat(deployment.getRepositoryUrl().toString(), endsWith("/repos/hub4j-test-org/github-api")); - } - - private GHRepository getRepository(final GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); } /** @@ -89,4 +82,8 @@ private GHRepository getRepository(final GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(final GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } } diff --git a/src/test/java/org/kohsuke/github/GHDiscussionTest.java b/src/test/java/org/kohsuke/github/GHDiscussionTest.java index 2a713647df..a2b68db1b5 100644 --- a/src/test/java/org/kohsuke/github/GHDiscussionTest.java +++ b/src/test/java/org/kohsuke/github/GHDiscussionTest.java @@ -18,15 +18,26 @@ */ public class GHDiscussionTest extends AbstractGitHubWireMockTest { - private final String TEAM_SLUG = "dummy-team"; - - private GHTeam team; /** * Create default GHDiscussionTest instance */ public GHDiscussionTest() { } + private final String TEAM_SLUG = "dummy-team"; + private GHTeam team; + + /** + * Sets the up. + * + * @throws Exception + * the exception + */ + @Before + public void setUp() throws Exception { + team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(TEAM_SLUG); + } + /** * Cleanup discussions. * @@ -45,17 +56,6 @@ public void cleanupDiscussions() throws Exception { } } - /** - * Sets the up. - * - * @throws Exception - * the exception - */ - @Before - public void setUp() throws Exception { - team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(TEAM_SLUG); - } - /** * Test created discussion. * diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index 506bb62269..638e60f18b 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -9,8 +9,10 @@ import org.kohsuke.github.GHTeam.Privacy; import java.io.IOException; +import java.text.SimpleDateFormat; import java.util.Collections; import java.util.List; +import java.util.TimeZone; import static org.hamcrest.Matchers.aMapWithSize; import static org.hamcrest.Matchers.contains; @@ -44,163 +46,119 @@ public GHEventPayloadTest() { } /** - * Installation event. + * Commit comment. * * @throws Exception * the exception */ @Test - @Payload("installation_created") - public void InstallationCreatedEvent() throws Exception { - final GHEventPayload.Installation event = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) - .build() - .parseEventPayload(payload.asReader(), GHEventPayload.Installation.class); - + public void commit_comment() throws Exception { + final GHEventPayload.CommitComment event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.CommitComment.class); assertThat(event.getAction(), is("created")); - assertThat(event.getInstallation().getId(), is(43898337L)); - assertThat(event.getInstallation().getAccount().getLogin(), is("CronFire")); - - assertThat(event.getRepositories().isEmpty(), is(false)); - assertThat(event.getRepositories().get(0).getId(), is(1296269L)); - assertThat(event.getRawRepositories().isEmpty(), is(false)); - assertThat(event.getRawRepositories().get(0).getId(), is(1296269L)); + assertThat(event.getComment().getSHA1(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getComment().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); - assertThat(event.getSender().getLogin(), is("Haarolean")); + assertThat(event.getComment().getOwner(), sameInstance(event.getRepository())); } /** - * Installation event. + * Creates the. * * @throws Exception * the exception */ @Test - @Payload("installation_deleted") - public void InstallationDeletedEvent() throws Exception { - final GHEventPayload.Installation event = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) - .build() - .parseEventPayload(payload.asReader(), GHEventPayload.Installation.class); - - assertThat(event.getAction(), is("deleted")); - assertThat(event.getInstallation().getId(), is(2L)); - assertThat(event.getInstallation().getAccount().getLogin(), is("octocat")); - - assertThrows(IllegalStateException.class, () -> event.getRepositories().isEmpty()); - assertThat(event.getRawRepositories().isEmpty(), is(false)); - assertThat(event.getRawRepositories().get(0).getId(), is(1296269L)); - assertThat(event.getRawRepositories().get(0).getNodeId(), is("MDEwOlJlcG9zaXRvcnkxMjk2MjY5")); - assertThat(event.getRawRepositories().get(0).getName(), is("Hello-World")); - assertThat(event.getRawRepositories().get(0).getFullName(), is("octocat/Hello-World")); - assertThat(event.getRawRepositories().get(0).isPrivate(), is(false)); - - assertThat(event.getSender().getLogin(), is("octocat")); + public void create() throws Exception { + final GHEventPayload.Create event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Create.class); + assertThat(event.getRef(), is("0.0.1")); + assertThat(event.getRefType(), is("tag")); + assertThat(event.getMasterBranch(), is("main")); + assertThat(event.getDescription(), is("")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); } /** - * Installation repositories event. + * Delete. * * @throws Exception * the exception */ @Test - @Payload("installation_repositories") - public void InstallationRepositoriesEvent() throws Exception { - final GHEventPayload.InstallationRepositories event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.InstallationRepositories.class); - - assertThat(event.getAction(), is("added")); - assertThat(event.getInstallation().getId(), is(957387L)); - assertThat(event.getInstallation().getAccount().getLogin(), is("Codertocat")); - assertThat(event.getRepositorySelection(), is("selected")); - - assertThat(event.getRepositoriesAdded().get(0).getId(), is(186853007L)); - assertThat(event.getRepositoriesAdded().get(0).getNodeId(), is("MDEwOlJlcG9zaXRvcnkxODY4NTMwMDc=")); - assertThat(event.getRepositoriesAdded().get(0).getName(), is("Space")); - assertThat(event.getRepositoriesAdded().get(0).getFullName(), is("Codertocat/Space")); - assertThat(event.getRepositoriesAdded().get(0).isPrivate(), is(false)); - - assertThat(event.getRepositoriesRemoved(), is(Collections.emptyList())); - assertThat(event.getSender().getLogin(), is("Codertocat")); + public void delete() throws Exception { + final GHEventPayload.Delete event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Delete.class); + assertThat(event.getRef(), is("simple-tag")); + assertThat(event.getRefType(), is("tag")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); } /** - * Check run event. + * Deployment. * * @throws Exception * the exception */ @Test - @Payload("check-run") - public void checkRunEvent() throws Exception { - final GHEventPayload.CheckRun event = GitHub.offline() - .parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), GHEventPayload.CheckRun.class); - final GHCheckRun checkRun = verifyBasicCheckRunEvent(event); - assertThat("pull body not populated offline", checkRun.getPullRequests().get(0).getBody(), nullValue()); - assertThat("using offline github", mockGitHub.getRequestCount(), equalTo(0)); - assertThat(checkRun.getPullRequests().get(0).getRepository(), sameInstance(event.getRepository())); - - gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); - final GHEventPayload.CheckRun event2 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), - GHEventPayload.CheckRun.class); - final GHCheckRun checkRun2 = verifyBasicCheckRunEvent(event2); + public void deployment() throws Exception { + final GHEventPayload.Deployment event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Deployment.class); + assertThat(event.getDeployment().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getDeployment().getEnvironment(), is("production")); + assertThat(event.getDeployment().getCreator().getLogin(), is("baxterthehacker")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); - int expectedRequestCount = 2; - assertThat("pull body should be populated", - checkRun2.getPullRequests().get(0).getBody(), - equalTo("This is a pretty simple change that we need to pull into main.")); - assertThat("multiple getPullRequests() calls are made, the pull is populated only once", - mockGitHub.getRequestCount(), - equalTo(expectedRequestCount)); + assertThat(event.getDeployment().getOwner(), sameInstance(event.getRepository())); } /** - * Check suite event. + * Deployment status. * * @throws Exception * the exception */ @Test - @Payload("check-suite") - public void checkSuiteEvent() throws Exception { - final GHEventPayload.CheckSuite event = GitHub.offline() - .parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), GHEventPayload.CheckSuite.class); - final GHCheckSuite checkSuite = verifyBasicCheckSuiteEvent(event); - assertThat("pull body not populated offline", checkSuite.getPullRequests().get(0).getBody(), nullValue()); - assertThat("using offline github", mockGitHub.getRequestCount(), equalTo(0)); - assertThat(checkSuite.getPullRequests().get(0).getRepository(), sameInstance(event.getRepository())); - - gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); - final GHEventPayload.CheckSuite event2 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), - GHEventPayload.CheckSuite.class); - final GHCheckSuite checkSuite2 = verifyBasicCheckSuiteEvent(event2); + public void deployment_status() throws Exception { + final GHEventPayload.DeploymentStatus event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.DeploymentStatus.class); + assertThat(event.getDeploymentStatus().getState(), is(GHDeploymentState.SUCCESS)); + assertThat(event.getDeploymentStatus().getLogUrl(), nullValue()); + assertThat(event.getDeployment().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getDeployment().getEnvironment(), is("production")); + assertThat(event.getDeployment().getCreator().getLogin(), is("baxterthehacker")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); - int expectedRequestCount = mockGitHub.isUseProxy() ? 3 : 2; - assertThat("pull body should be populated", - checkSuite2.getPullRequests().get(0).getBody(), - equalTo("This is a pretty simple change that we need to pull into main.")); - assertThat("multiple getPullRequests() calls are made, the pull is populated only once", - mockGitHub.getRequestCount(), - lessThanOrEqualTo(expectedRequestCount)); + assertThat(event.getDeployment().getOwner(), sameInstance(event.getRepository())); + assertThat(event.getDeploymentStatus().getOwner(), sameInstance(event.getRepository())); } /** - * Commit comment. + * Fork. * * @throws Exception * the exception */ @Test - public void commit_comment() throws Exception { - final GHEventPayload.CommitComment event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.CommitComment.class); - assertThat(event.getAction(), is("created")); - assertThat(event.getComment().getSHA1(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); - assertThat(event.getComment().getUser().getLogin(), is("baxterthehacker")); + public void fork() throws Exception { + final GHEventPayload.Fork event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Fork.class); + assertThat(event.getForkee().getName(), is("public-repo")); + assertThat(event.getForkee().getOwner().getLogin(), is("baxterandthehackers")); assertThat(event.getRepository().getName(), is("public-repo")); assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); - - assertThat(event.getComment().getOwner(), sameInstance(event.getRepository())); + assertThat(event.getSender().getLogin(), is("baxterandthehackers")); } // TODO uncomment when we have GHPage implemented @@ -222,261 +180,134 @@ public void commit_comment() throws Exception { // } /** - * Creates the. + * Issue comment. * * @throws Exception * the exception */ @Test - public void create() throws Exception { - final GHEventPayload.Create event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Create.class); - assertThat(event.getRef(), is("0.0.1")); - assertThat(event.getRefType(), is("tag")); - assertThat(event.getMasterBranch(), is("main")); - assertThat(event.getDescription(), is("")); + public void issue_comment() throws Exception { + final GHEventPayload.IssueComment event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.IssueComment.class); + assertThat(event.getAction(), is("created")); + assertThat(event.getIssue().getNumber(), is(2)); + assertThat(event.getIssue().getTitle(), is("Spelling error in the README file")); + assertThat(event.getIssue().getState(), is(GHIssueState.OPEN)); + assertThat(event.getIssue().getLabels().size(), is(1)); + assertThat(event.getIssue().getLabels().iterator().next().getName(), is("bug")); + assertThat(event.getComment().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getComment().getBody(), is("You are totally right! I'll get this fixed right away.")); assertThat(event.getRepository().getName(), is("public-repo")); assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); assertThat(event.getSender().getLogin(), is("baxterthehacker")); + + assertThat(event.getIssue().getRepository(), sameInstance(event.getRepository())); + assertThat(event.getComment().getParent(), sameInstance(event.getIssue())); } /** - * Delete. + * Issue comment edited. * * @throws Exception * the exception */ @Test - public void delete() throws Exception { - final GHEventPayload.Delete event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Delete.class); - assertThat(event.getRef(), is("simple-tag")); - assertThat(event.getRefType(), is("tag")); - assertThat(event.getRepository().getName(), is("public-repo")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); + public void issue_comment_edited() throws Exception { + final GHEventPayload.IssueComment event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.IssueComment.class); + assertThat(event.getAction(), is("edited")); + assertThat(event.getComment().getBody(), is("This is the issue comment AFTER edit.")); + assertThat(event.getChanges().getBody().getFrom(), is("This is the issue comment BEFORE edit.")); } /** - * Deployment. + * Issues. * * @throws Exception * the exception */ @Test - public void deployment() throws Exception { - final GHEventPayload.Deployment event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Deployment.class); - assertThat(event.getDeployment().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); - assertThat(event.getDeployment().getEnvironment(), is("production")); - assertThat(event.getDeployment().getCreator().getLogin(), is("baxterthehacker")); + public void issues() throws Exception { + final GHEventPayload.Issue event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); + assertThat(event.getAction(), is("opened")); + assertThat(event.getIssue().getNumber(), is(2)); + assertThat(event.getIssue().getTitle(), is("Spelling error in the README file")); + assertThat(event.getIssue().getState(), is(GHIssueState.OPEN)); + assertThat(event.getIssue().getLabels().size(), is(1)); + assertThat(event.getIssue().getLabels().iterator().next().getName(), is("bug")); assertThat(event.getRepository().getName(), is("public-repo")); assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); assertThat(event.getSender().getLogin(), is("baxterthehacker")); - assertThat(event.getDeployment().getOwner(), sameInstance(event.getRepository())); + assertThat(event.getIssue().getRepository(), sameInstance(event.getRepository())); } /** - * Deployment status. + * Issue labeled. * * @throws Exception * the exception */ @Test - public void deployment_status() throws Exception { - final GHEventPayload.DeploymentStatus event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.DeploymentStatus.class); - assertThat(event.getDeploymentStatus().getState(), is(GHDeploymentState.SUCCESS)); - assertThat(event.getDeploymentStatus().getLogUrl(), nullValue()); - assertThat(event.getDeployment().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); - assertThat(event.getDeployment().getEnvironment(), is("production")); - assertThat(event.getDeployment().getCreator().getLogin(), is("baxterthehacker")); - assertThat(event.getRepository().getName(), is("public-repo")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); - - assertThat(event.getDeployment().getOwner(), sameInstance(event.getRepository())); - assertThat(event.getDeploymentStatus().getOwner(), sameInstance(event.getRepository())); + public void issue_labeled() throws Exception { + final GHEventPayload.Issue event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); + assertThat(event.getAction(), is("labeled")); + assertThat(event.getIssue().getNumber(), is(42)); + assertThat(event.getIssue().getTitle(), is("Test GHEventPayload.Issue label/unlabel")); + assertThat(event.getIssue().getLabels().size(), is(1)); + assertThat(event.getIssue().getLabels().iterator().next().getName(), is("enhancement")); + assertThat(event.getLabel().getName(), is("enhancement")); } /** - * Discussion answered. + * Issue unlabeled. * * @throws Exception * the exception */ @Test - public void discussion_answered() throws Exception { - final GHEventPayload.Discussion discussionPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Discussion.class); - - assertThat(discussionPayload.getAction(), is("answered")); - assertThat(discussionPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(discussionPayload.getSender().getLogin(), is("gsmet")); - - GHRepositoryDiscussion discussion = discussionPayload.getDiscussion(); - - GHRepositoryDiscussion.Category category = discussion.getCategory(); - - assertThat(category.getId(), is(33522033L)); - assertThat(category.getNodeId(), is("DIC_kwDOEq3cwc4B_4Fx")); - assertThat(category.getEmoji(), is(":pray:")); - assertThat(category.getName(), is("Q&A")); - assertThat(category.getDescription(), is("Ask the community for help")); - assertThat(category.getCreatedAt().toEpochMilli(), is(1636991431000L)); - assertThat(category.getUpdatedAt().toEpochMilli(), is(1636991431000L)); - assertThat(category.getSlug(), is("q-a")); - assertThat(category.isAnswerable(), is(true)); - - assertThat(discussion.getAnswerHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/78#discussioncomment-1681242")); - assertThat(discussion.getAnswerChosenAt().toEpochMilli(), is(1637585047000L)); - assertThat(discussion.getAnswerChosenBy().getLogin(), is("gsmet")); - - assertThat(discussion.getHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/78")); - assertThat(discussion.getId(), is(3698909L)); - assertThat(discussion.getNodeId(), is("D_kwDOEq3cwc4AOHDd")); - assertThat(discussion.getNumber(), is(78)); - assertThat(discussion.getTitle(), is("Title of discussion")); - - assertThat(discussion.getUser().getLogin(), is("gsmet")); - assertThat(discussion.getUser().getId(), is(1279749L)); - assertThat(discussion.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); - - assertThat(discussion.getState(), is(GHRepositoryDiscussion.State.OPEN)); - assertThat(discussion.isLocked(), is(false)); - assertThat(discussion.getComments(), is(1)); - assertThat(discussion.getCreatedAt().toEpochMilli(), is(1637584949000L)); - assertThat(discussion.getUpdatedAt().toEpochMilli(), is(1637585047000L)); - assertThat(discussion.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); - assertThat(discussion.getActiveLockReason(), is(nullValue())); - assertThat(discussion.getBody(), is("Body of discussion.")); + public void issue_unlabeled() throws Exception { + final GHEventPayload.Issue event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); + assertThat(event.getAction(), is("unlabeled")); + assertThat(event.getIssue().getNumber(), is(42)); + assertThat(event.getIssue().getTitle(), is("Test GHEventPayload.Issue label/unlabel")); + assertThat(event.getIssue().getLabels().size(), is(0)); + assertThat(event.getLabel().getName(), is("enhancement")); } /** - * Discussion comment created. + * Issue title edited. * * @throws Exception * the exception */ @Test - public void discussion_comment_created() throws Exception { - final GHEventPayload.DiscussionComment discussionCommentPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.DiscussionComment.class); - - assertThat(discussionCommentPayload.getAction(), is("created")); - assertThat(discussionCommentPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(discussionCommentPayload.getSender().getLogin(), is("gsmet")); - - GHRepositoryDiscussion discussion = discussionCommentPayload.getDiscussion(); - - GHRepositoryDiscussion.Category category = discussion.getCategory(); - - assertThat(category.getId(), is(33522033L)); - assertThat(category.getNodeId(), is("DIC_kwDOEq3cwc4B_4Fx")); - assertThat(category.getEmoji(), is(":pray:")); - assertThat(category.getName(), is("Q&A")); - assertThat(category.getDescription(), is("Ask the community for help")); - assertThat(category.getCreatedAt().toEpochMilli(), is(1636991431000L)); - assertThat(category.getUpdatedAt().toEpochMilli(), is(1636991431000L)); - assertThat(category.getSlug(), is("q-a")); - assertThat(category.isAnswerable(), is(true)); - - assertThat(discussion.getAnswerHtmlUrl(), is(nullValue())); - assertThat(discussion.getAnswerChosenAt(), is(nullValue())); - assertThat(discussion.getAnswerChosenBy(), is(nullValue())); - - assertThat(discussion.getHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/162")); - assertThat(discussion.getId(), is(6090566L)); - assertThat(discussion.getNodeId(), is("D_kwDOEq3cwc4AXO9G")); - assertThat(discussion.getNumber(), is(162)); - assertThat(discussion.getTitle(), is("New test question")); - - assertThat(discussion.getUser().getLogin(), is("gsmet")); - assertThat(discussion.getUser().getId(), is(1279749L)); - assertThat(discussion.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); - - assertThat(discussion.getState(), is(GHRepositoryDiscussion.State.OPEN)); - assertThat(discussion.isLocked(), is(false)); - assertThat(discussion.getComments(), is(1)); - assertThat(discussion.getCreatedAt().toEpochMilli(), is(1705586390000L)); - assertThat(discussion.getUpdatedAt().toEpochMilli(), is(1705586399000L)); - assertThat(discussion.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); - assertThat(discussion.getActiveLockReason(), is(nullValue())); - assertThat(discussion.getBody(), is("Test question")); - - GHRepositoryDiscussionComment comment = discussionCommentPayload.getComment(); - - assertThat(comment.getHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/162#discussioncomment-8169669")); - assertThat(comment.getId(), is(8169669L)); - assertThat(comment.getNodeId(), is("DC_kwDOEq3cwc4AfKjF")); - assertThat(comment.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); - assertThat(comment.getCreatedAt().toEpochMilli(), is(1705586398000L)); - assertThat(comment.getUpdatedAt().toEpochMilli(), is(1705586399000L)); - assertThat(comment.getBody(), is("Test comment.")); - assertThat(comment.getUser().getLogin(), is("gsmet")); - assertThat(comment.getUser().getId(), is(1279749L)); - assertThat(comment.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); - assertThat(comment.getParentId(), is(nullValue())); - assertThat(comment.getChildCommentCount(), is(0)); + public void issue_title_edited() throws Exception { + final GHEventPayload.Issue event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); + assertThat(event.getAction(), is("edited")); + assertThat(event.getIssue().getNumber(), is(43)); + assertThat(event.getIssue().getTitle(), is("Test GHEventPayload.Issue changes [updated]")); + assertThat(event.getChanges().getTitle().getFrom(), is("Test GHEventPayload.Issue changes")); } /** - * Discussion created. + * Issue body edited. * * @throws Exception * the exception */ @Test - public void discussion_created() throws Exception { - final GHEventPayload.Discussion discussionPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Discussion.class); - - assertThat(discussionPayload.getAction(), is("created")); - assertThat(discussionPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(discussionPayload.getSender().getLogin(), is("gsmet")); - - GHRepositoryDiscussion discussion = discussionPayload.getDiscussion(); - - GHRepositoryDiscussion.Category category = discussion.getCategory(); - - assertThat(category.getId(), is(33522033L)); - assertThat(category.getNodeId(), is("DIC_kwDOEq3cwc4B_4Fx")); - assertThat(category.getEmoji(), is(":pray:")); - assertThat(category.getName(), is("Q&A")); - assertThat(category.getDescription(), is("Ask the community for help")); - assertThat(category.getCreatedAt().toEpochMilli(), is(1636991431000L)); - assertThat(category.getUpdatedAt().toEpochMilli(), is(1636991431000L)); - assertThat(category.getSlug(), is("q-a")); - assertThat(category.isAnswerable(), is(true)); - - assertThat(discussion.getAnswerHtmlUrl(), is(nullValue())); - assertThat(discussion.getAnswerChosenAt(), is(nullValue())); - assertThat(discussion.getAnswerChosenBy(), is(nullValue())); - - assertThat(discussion.getHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/78")); - assertThat(discussion.getId(), is(3698909L)); - assertThat(discussion.getNodeId(), is("D_kwDOEq3cwc4AOHDd")); - assertThat(discussion.getNumber(), is(78)); - assertThat(discussion.getTitle(), is("Title of discussion")); - - assertThat(discussion.getUser().getLogin(), is("gsmet")); - assertThat(discussion.getUser().getId(), is(1279749L)); - assertThat(discussion.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); - - assertThat(discussion.getState(), is(GHRepositoryDiscussion.State.OPEN)); - assertThat(discussion.isLocked(), is(false)); - assertThat(discussion.getComments(), is(0)); - assertThat(discussion.getCreatedAt().toEpochMilli(), is(1637584949000L)); - assertThat(discussion.getUpdatedAt().toEpochMilli(), is(1637584949000L)); - assertThat(discussion.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); - assertThat(discussion.getActiveLockReason(), is(nullValue())); - assertThat(discussion.getBody(), is("Body of discussion.")); + public void issue_body_edited() throws Exception { + final GHEventPayload.Issue event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); + assertThat(event.getAction(), is("edited")); + assertThat(event.getIssue().getNumber(), is(43)); + assertThat(event.getIssue().getBody(), is("Description [updated].")); + assertThat(event.getChanges().getBody().getFrom(), is("Description.")); } // TODO implement support classes and write test @@ -500,1046 +331,1466 @@ public void discussion_created() throws Exception { // public void page_build() throws Exception {} /** - * Discussion labeled. + * Ping. * * @throws Exception * the exception */ @Test - public void discussion_labeled() throws Exception { - final GHEventPayload.Discussion discussionPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Discussion.class); - - assertThat(discussionPayload.getAction(), is("labeled")); - assertThat(discussionPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(discussionPayload.getSender().getLogin(), is("gsmet")); - - GHRepositoryDiscussion discussion = discussionPayload.getDiscussion(); - - GHRepositoryDiscussion.Category category = discussion.getCategory(); - - assertThat(category.getId(), is(33522033L)); - assertThat(category.getNodeId(), is("DIC_kwDOEq3cwc4B_4Fx")); - assertThat(category.getEmoji(), is(":pray:")); - assertThat(category.getName(), is("Q&A")); - assertThat(category.getDescription(), is("Ask the community for help")); - assertThat(category.getCreatedAt().toEpochMilli(), is(1636991431000L)); - assertThat(category.getUpdatedAt().toEpochMilli(), is(1636991431000L)); - assertThat(category.getSlug(), is("q-a")); - assertThat(category.isAnswerable(), is(true)); - - assertThat(discussion.getAnswerHtmlUrl(), is(nullValue())); - assertThat(discussion.getAnswerChosenAt(), is(nullValue())); - assertThat(discussion.getAnswerChosenBy(), is(nullValue())); - - assertThat(discussion.getHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/78")); - assertThat(discussion.getId(), is(3698909L)); - assertThat(discussion.getNodeId(), is("D_kwDOEq3cwc4AOHDd")); - assertThat(discussion.getNumber(), is(78)); - assertThat(discussion.getTitle(), is("Title of discussion")); - - assertThat(discussion.getUser().getLogin(), is("gsmet")); - assertThat(discussion.getUser().getId(), is(1279749L)); - assertThat(discussion.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); - - assertThat(discussion.getState(), is(GHRepositoryDiscussion.State.OPEN)); - assertThat(discussion.isLocked(), is(false)); - assertThat(discussion.getComments(), is(0)); - assertThat(discussion.getCreatedAt().toEpochMilli(), is(1637584949000L)); - assertThat(discussion.getUpdatedAt().toEpochMilli(), is(1637584961000L)); - assertThat(discussion.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); - assertThat(discussion.getActiveLockReason(), is(nullValue())); - assertThat(discussion.getBody(), is("Body of discussion.")); + public void ping() throws Exception { + final GHEventPayload.Ping event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Ping.class); - GHLabel label = discussionPayload.getLabel(); - assertThat(label.getId(), is(2543373314L)); - assertThat(label.getNodeId(), is("MDU6TGFiZWwyNTQzMzczMzE0")); - assertThat(label.getUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/labels/area/hibernate-validator")); - assertThat(label.getName(), is("area/hibernate-validator")); - assertThat(label.getColor(), is("ededed")); - assertThat(label.isDefault(), is(false)); - assertThat(label.getDescription(), is(nullValue())); + assertThat(event.getAction(), nullValue()); + assertThat(event.getSender().getLogin(), is("seregamorph")); + assertThat(event.getRepository().getName(), is("acme-project-project")); + assertThat(event.getOrganization(), nullValue()); } /** - * Fork. + * Public. * * @throws Exception * the exception */ @Test - public void fork() throws Exception { - final GHEventPayload.Fork event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Fork.class); - assertThat(event.getForkee().getName(), is("public-repo")); - assertThat(event.getForkee().getOwner().getLogin(), is("baxterandthehackers")); + @Payload("public") + public void public_() throws Exception { + final GHEventPayload.Public event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Public.class); assertThat(event.getRepository().getName(), is("public-repo")); assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); - assertThat(event.getSender().getLogin(), is("baxterandthehackers")); - } - - /** - * Issue body edited. - * - * @throws Exception - * the exception - */ - @Test - public void issue_body_edited() throws Exception { - final GHEventPayload.Issue event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); - assertThat(event.getAction(), is("edited")); - assertThat(event.getIssue().getNumber(), is(43)); - assertThat(event.getIssue().getBody(), is("Description [updated].")); - assertThat(event.getChanges().getBody().getFrom(), is("Description.")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); } /** - * Issue comment. + * Pull request. * * @throws Exception * the exception */ @Test - public void issue_comment() throws Exception { - final GHEventPayload.IssueComment event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.IssueComment.class); - assertThat(event.getAction(), is("created")); - assertThat(event.getIssue().getNumber(), is(2)); - assertThat(event.getIssue().getTitle(), is("Spelling error in the README file")); - assertThat(event.getIssue().getState(), is(GHIssueState.OPEN)); - assertThat(event.getIssue().getLabels().size(), is(1)); - assertThat(event.getIssue().getLabels().iterator().next().getName(), is("bug")); - assertThat(event.getComment().getUser().getLogin(), is("baxterthehacker")); - assertThat(event.getComment().getBody(), is("You are totally right! I'll get this fixed right away.")); - assertThat(event.getComment().getAuthorAssociation(), equalTo(GHCommentAuthorAssociation.UNKNOWN)); - assertThat(event.getComment().getBody(), is("You are totally right! I'll get this fixed right away.")); + public void pull_request() throws Exception { + final GHEventPayload.PullRequest event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); + assertThat(event.getAction(), is("opened")); + assertThat(event.getNumber(), is(1)); + assertThat(event.getPullRequest().getNumber(), is(1)); + assertThat(event.getPullRequest().getTitle(), is("Update the README with new information")); + assertThat(event.getPullRequest().getBody(), + is("This is a pretty simple change that we need to pull into " + "main.")); + assertThat(event.getPullRequest().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getHead().getRef(), is("changes")); + assertThat(event.getPullRequest().getHead().getLabel(), is("baxterthehacker:changes")); + assertThat(event.getPullRequest().getHead().getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getBase().getRef(), is("main")); + assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:main")); + assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getPullRequest().isMerged(), is(false)); + assertThat(event.getPullRequest().getMergeable(), nullValue()); + assertThat(event.getPullRequest().getMergeableState(), is("unknown")); + assertThat(event.getPullRequest().getMergedBy(), nullValue()); + assertThat(event.getPullRequest().getCommentsCount(), is(0)); + assertThat(event.getPullRequest().getReviewComments(), is(0)); + assertThat(event.getPullRequest().getAdditions(), is(1)); + assertThat(event.getPullRequest().getDeletions(), is(1)); + assertThat(event.getPullRequest().getChangedFiles(), is(1)); assertThat(event.getRepository().getName(), is("public-repo")); assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); assertThat(event.getSender().getLogin(), is("baxterthehacker")); - assertThat(event.getIssue().getRepository(), sameInstance(event.getRepository())); - assertThat(event.getComment().getParent(), sameInstance(event.getIssue())); + assertThat(event.getPullRequest().getRepository(), sameInstance(event.getRepository())); } /** - * Issue comment edited. + * Pull request edited base. * * @throws Exception * the exception */ @Test - public void issue_comment_edited() throws Exception { - final GHEventPayload.IssueComment event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.IssueComment.class); + public void pull_request_edited_base() throws Exception { + final GHEventPayload.PullRequest event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); + assertThat(event.getAction(), is("edited")); - assertThat(event.getComment().getBody(), is("This is the issue comment AFTER edit.")); - assertThat(event.getChanges().getBody().getFrom(), is("This is the issue comment BEFORE edit.")); + assertThat(event.getChanges().getTitle(), nullValue()); + assertThat(event.getPullRequest().getTitle(), is("REST-276 - easy-random")); + assertThat(event.getChanges().getBase().getRef().getFrom(), is("develop")); + assertThat(event.getChanges().getBase().getSha().getFrom(), is("4b0f3b9fd582b071652ccfccd10bfc8c143cff96")); + assertThat(event.getPullRequest().getBase().getRef(), is("4.3")); + assertThat(event.getPullRequest().getBody(), startsWith("**JIRA Ticket URL:**")); + assertThat(event.getChanges().getBody(), nullValue()); } /** - * Issue labeled. + * Pull request edited title. * * @throws Exception * the exception */ @Test - public void issue_labeled() throws Exception { - final GHEventPayload.Issue event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); - assertThat(event.getAction(), is("labeled")); - assertThat(event.getIssue().getNumber(), is(42)); - assertThat(event.getIssue().getTitle(), is("Test GHEventPayload.Issue label/unlabel")); - assertThat(event.getIssue().getLabels().size(), is(1)); - assertThat(event.getIssue().getLabels().iterator().next().getName(), is("enhancement")); - assertThat(event.getLabel().getName(), is("enhancement")); - } + public void pull_request_edited_title() throws Exception { + final GHEventPayload.PullRequest event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); - /** - * Issue title edited. - * - * @throws Exception - * the exception - */ - @Test - public void issue_title_edited() throws Exception { - final GHEventPayload.Issue event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); assertThat(event.getAction(), is("edited")); - assertThat(event.getIssue().getNumber(), is(43)); - assertThat(event.getIssue().getTitle(), is("Test GHEventPayload.Issue changes [updated]")); - assertThat(event.getChanges().getTitle().getFrom(), is("Test GHEventPayload.Issue changes")); + assertThat(event.getChanges().getTitle().getFrom(), is("REST-276 - easy-random")); + assertThat(event.getPullRequest().getTitle(), is("REST-276 - easy-random 4.3.0")); + assertThat(event.getChanges().getBase(), nullValue()); + assertThat(event.getPullRequest().getBase().getRef(), is("4.3")); + assertThat(event.getPullRequest().getBody(), startsWith("**JIRA Ticket URL:**")); + assertThat(event.getChanges().getBody(), nullValue()); } /** - * Issue unlabeled. + * Pull request labeled. * * @throws Exception * the exception */ @Test - public void issue_unlabeled() throws Exception { - final GHEventPayload.Issue event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); - assertThat(event.getAction(), is("unlabeled")); - assertThat(event.getIssue().getNumber(), is(42)); - assertThat(event.getIssue().getTitle(), is("Test GHEventPayload.Issue label/unlabel")); - assertThat(event.getIssue().getLabels().size(), is(0)); - assertThat(event.getLabel().getName(), is("enhancement")); + public void pull_request_labeled() throws Exception { + final GHEventPayload.PullRequest event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); + assertThat(event.getAction(), is("labeled")); + assertThat(event.getNumber(), is(79)); + assertThat(event.getPullRequest().getNumber(), is(79)); + assertThat(event.getPullRequest().getTitle(), is("Base POJO test enhancement")); + assertThat(event.getPullRequest().getBody(), + is("This is a pretty simple change that we need to pull into develop.")); + assertThat(event.getPullRequest().getUser().getLogin(), is("seregamorph")); + assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("trilogy-group")); + assertThat(event.getPullRequest().getHead().getRef(), is("changes")); + assertThat(event.getPullRequest().getHead().getLabel(), is("trilogy-group:changes")); + assertThat(event.getPullRequest().getHead().getSha(), is("4b91e3a970fb967fb7be4d52e0969f8e3fb063d0")); + assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("trilogy-group")); + assertThat(event.getPullRequest().getBase().getRef(), is("3.10")); + assertThat(event.getPullRequest().getBase().getLabel(), is("trilogy-group:3.10")); + assertThat(event.getPullRequest().getBase().getSha(), is("7a735f17d686c6a1fc7df5b9d395e5863868f364")); + assertThat(event.getPullRequest().isMerged(), is(false)); + assertThat(event.getPullRequest().getMergeable(), is(true)); + assertThat(event.getPullRequest().getMergeableState(), is("draft")); + assertThat(event.getPullRequest().getMergedBy(), nullValue()); + assertThat(event.getPullRequest().getCommentsCount(), is(1)); + assertThat(event.getPullRequest().getReviewComments(), is(14)); + assertThat(event.getPullRequest().getAdditions(), is(137)); + assertThat(event.getPullRequest().getDeletions(), is(81)); + assertThat(event.getPullRequest().getChangedFiles(), is(22)); + assertThat(event.getPullRequest().getLabels().iterator().next().getName(), is("Ready for Review")); + assertThat(event.getRepository().getName(), is("trilogy-rest-api-framework")); + assertThat(event.getRepository().getOwner().getLogin(), is("trilogy-group")); + assertThat(event.getSender().getLogin(), is("schernov-xo")); + assertThat(event.getLabel().getUrl(), + is("https://api.github.com/repos/trilogy-group/trilogy-rest-api-framework/labels/rest%20api")); + assertThat(event.getLabel().getName(), is("rest api")); + assertThat(event.getLabel().getColor(), is("fef2c0")); + assertThat(event.getLabel().getDescription(), is("REST API pull request")); + assertThat(event.getOrganization().getLogin(), is("trilogy-group")); } /** - * Issues. + * Pull request review. * * @throws Exception * the exception */ @Test - public void issues() throws Exception { - final GHEventPayload.Issue event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Issue.class); - assertThat(event.getAction(), is("opened")); - assertThat(event.getIssue().getNumber(), is(2)); - assertThat(event.getIssue().getTitle(), is("Spelling error in the README file")); - assertThat(event.getIssue().getState(), is(GHIssueState.OPEN)); - assertThat(event.getIssue().getLabels().size(), is(1)); - assertThat(event.getIssue().getLabels().iterator().next().getName(), is("bug")); + public void pull_request_review() throws Exception { + final GHEventPayload.PullRequestReview event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReview.class); + assertThat(event.getAction(), is("submitted")); + + assertThat(event.getReview().getId(), is(2626884L)); + assertThat(event.getReview().getBody(), is("Looks great!\n")); + assertThat(event.getReview().getState(), is(GHPullRequestReviewState.APPROVED)); + + assertThat(event.getPullRequest().getNumber(), is(8)); + assertThat(event.getPullRequest().getTitle(), is("Add a README description")); + assertThat(event.getPullRequest().getBody(), is("Just a few more details")); + assertThat(event.getReview().getHtmlUrl(), + hasToString("https://github.com/baxterthehacker/public-repo/pull/8#pullrequestreview-2626884")); + assertThat(event.getPullRequest().getUser().getLogin(), is("skalnik")); + assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("skalnik")); + assertThat(event.getPullRequest().getHead().getRef(), is("patch-2")); + assertThat(event.getPullRequest().getHead().getLabel(), is("skalnik:patch-2")); + assertThat(event.getPullRequest().getHead().getSha(), is("b7a1f9c27caa4e03c14a88feb56e2d4f7500aa63")); + assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getBase().getRef(), is("main")); + assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:main")); + assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getRepository().getName(), is("public-repo")); assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); - assertThat(event.getIssue().getRepository(), sameInstance(event.getRepository())); + assertThat(event.getPullRequest().getRepository(), sameInstance(event.getRepository())); + assertThat(event.getReview().getParent(), sameInstance(event.getPullRequest())); } /** - * Label created. + * Pull request review comment. * * @throws Exception * the exception */ @Test - public void label_created() throws Exception { - final GHEventPayload.Label labelPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Label.class); - GHLabel label = labelPayload.getLabel(); + public void pull_request_review_comment() throws Exception { + final GHEventPayload.PullRequestReviewComment event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReviewComment.class); + assertThat(event.getAction(), is("created")); - assertThat(labelPayload.getAction(), is("created")); - assertThat(labelPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(label.getId(), is(2901546662L)); - assertThat(label.getNodeId(), is("MDU6TGFiZWwyOTAxNTQ2NjYy")); - assertThat(label.getName(), is("new-label")); - assertThat(label.getColor(), is("f9d0c4")); - assertThat(label.isDefault(), is(false)); - assertThat(label.getDescription(), is("description")); + assertThat(event.getComment().getBody(), is("Maybe you should use more emojji on this line.")); + + assertThat(event.getPullRequest().getNumber(), is(1)); + assertThat(event.getPullRequest().getTitle(), is("Update the README with new information")); + assertThat(event.getPullRequest().getBody(), + is("This is a pretty simple change that we need to pull into main.")); + assertThat(event.getPullRequest().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getHead().getRef(), is("changes")); + assertThat(event.getPullRequest().getHead().getLabel(), is("baxterthehacker:changes")); + assertThat(event.getPullRequest().getHead().getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getBase().getRef(), is("main")); + assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:main")); + assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + + assertThat(event.getPullRequest().getRepository(), sameInstance(event.getRepository())); + assertThat(event.getComment().getParent(), sameInstance(event.getPullRequest())); } /** - * Label deleted. + * Pull request review comment edited. * * @throws Exception * the exception */ @Test - public void label_deleted() throws Exception { - GHEventPayload.Label labelPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Label.class); - GHLabel label = labelPayload.getLabel(); - - assertThat(labelPayload.getAction(), is("deleted")); - assertThat(labelPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(label.getId(), is(2901546662L)); - assertThat(label.getNodeId(), is("MDU6TGFiZWwyOTAxNTQ2NjYy")); - assertThat(label.getName(), is("new-label-updated")); - assertThat(label.getColor(), is("4AE686")); - assertThat(label.isDefault(), is(false)); - assertThat(label.getDescription(), is("description")); + public void pull_request_review_comment_edited() throws Exception { + final GHEventPayload.PullRequestReviewComment event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReviewComment.class); + assertThat(event.getAction(), is("edited")); + assertThat(event.getPullRequest().getNumber(), is(4)); + assertThat(event.getComment().getBody(), is("This is the pull request review comment AFTER edit.")); + assertThat(event.getChanges().getBody().getFrom(), is("This is the pull request review comment BEFORE edit.")); } /** - * Label edited. + * Push. * * @throws Exception * the exception */ @Test - public void label_edited() throws Exception { - final GHEventPayload.Label labelPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Label.class); - GHLabel label = labelPayload.getLabel(); - - assertThat(labelPayload.getAction(), is("edited")); - assertThat(labelPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(label.getId(), is(2901546662L)); - assertThat(label.getNodeId(), is("MDU6TGFiZWwyOTAxNTQ2NjYy")); - assertThat(label.getName(), is("new-label-updated")); - assertThat(label.getColor(), is("4AE686")); - assertThat(label.isDefault(), is(false)); - assertThat(label.getDescription(), is("description")); - - assertThat(labelPayload.getChanges().getName().getFrom(), is("new-label")); - assertThat(labelPayload.getChanges().getColor().getFrom(), is("f9d0c4")); - } + public void push() throws Exception { + final GHEventPayload.Push event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Push.class); + assertThat(event.getRef(), is("refs/heads/changes")); + assertThat(event.getBefore(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getHead(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.isCreated(), is(false)); + assertThat(event.isDeleted(), is(false)); + assertThat(event.isForced(), is(false)); + assertThat(event.getCommits().size(), is(1)); + assertThat(event.getCommits().get(0).getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.getCommits().get(0).getAuthor().getEmail(), is("baxterthehacker@users.noreply.github.com")); + assertThat(event.getCommits().get(0).getAuthor().getUsername(), is("baxterthehacker")); + assertThat(event.getCommits().get(0).getCommitter().getEmail(), is("baxterthehacker@users.noreply.github.com")); + assertThat(event.getCommits().get(0).getCommitter().getUsername(), is("baxterthehacker")); + assertThat(event.getCommits().get(0).getAdded().size(), is(0)); + assertThat(event.getCommits().get(0).getRemoved().size(), is(0)); + assertThat(event.getCommits().get(0).getModified().size(), is(1)); + assertThat(event.getCommits().get(0).getModified().get(0), is("README.md")); + + assertThat(event.getHeadCommit().getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.getHeadCommit().getAuthor().getEmail(), is("baxterthehacker@users.noreply.github.com")); + assertThat(event.getHeadCommit().getAuthor().getUsername(), is("baxterthehacker")); + assertThat(event.getHeadCommit().getCommitter().getEmail(), is("baxterthehacker@users.noreply.github.com")); + assertThat(event.getHeadCommit().getCommitter().getUsername(), is("baxterthehacker")); + assertThat(event.getHeadCommit().getAdded().size(), is(0)); + assertThat(event.getHeadCommit().getRemoved().size(), is(0)); + assertThat(event.getHeadCommit().getModified().size(), is(1)); + assertThat(event.getHeadCommit().getModified().get(0), is("README.md")); + assertThat(event.getHeadCommit().getMessage(), is("Update README.md")); + + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + formatter.setTimeZone(TimeZone.getTimeZone("UTC")); + assertThat(formatter.format(event.getCommits().get(0).getTimestamp()), is("2015-05-05T23:40:15Z")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwnerName(), is("baxterthehacker")); + assertThat(event.getRepository().getUrl().toExternalForm(), + is("https://github.com/baxterthehacker/public-repo")); + assertThat(event.getPusher().getName(), is("baxterthehacker")); + assertThat(event.getPusher().getEmail(), is("baxterthehacker@users.noreply.github.com")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + assertThat(event.getCompare(), + is("https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f")); + } /** - * Member added. + * Push to fork. * * @throws Exception * the exception */ @Test - public void member_added() throws Exception { - final GHEventPayload.Member memberPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Member.class); + @Payload("push.fork") + public void pushToFork() throws Exception { + gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); - assertThat(memberPayload.getAction(), is("added")); + final GHEventPayload.Push event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Push.class); + assertThat(event.getRef(), is("refs/heads/changes")); + assertThat(event.getBefore(), is("85c44b352958bf6d81b74ab8b21920f1d313a287")); + assertThat(event.getHead(), is("1393706f1364742defbc28ba459082630ca979af")); + assertThat(event.isCreated(), is(false)); + assertThat(event.isDeleted(), is(false)); + assertThat(event.isForced(), is(false)); + assertThat(event.getCommits().size(), is(1)); + assertThat(event.getCommits().get(0).getSha(), is("1393706f1364742defbc28ba459082630ca979af")); + assertThat(event.getCommits().get(0).getAuthor().getEmail(), is("bitwiseman@gmail.com")); + assertThat(event.getCommits().get(0).getCommitter().getEmail(), is("bitwiseman@gmail.com")); + assertThat(event.getCommits().get(0).getAdded().size(), is(6)); + assertThat(event.getCommits().get(0).getRemoved().size(), is(0)); + assertThat(event.getCommits().get(0).getModified().size(), is(2)); + assertThat(event.getCommits().get(0).getModified().get(0), + is("src/main/java/org/kohsuke/github/GHLicense.java")); + assertThat(event.getRepository().getName(), is("github-api")); + assertThat(event.getRepository().getOwnerName(), is("hub4j-test-org")); + assertThat(event.getRepository().getUrl().toExternalForm(), is("https://github.com/hub4j-test-org/github-api")); + assertThat(event.getPusher().getName(), is("bitwiseman")); + assertThat(event.getPusher().getEmail(), is("bitwiseman@gmail.com")); + assertThat(event.getSender().getLogin(), is("bitwiseman")); - assertThat(memberPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); - assertThat(memberPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-playground")); + assertThat(event.getRepository().isFork(), is(true)); - GHUser member = memberPayload.getMember(); - assertThat(member.getId(), is(412878L)); - assertThat(member.getLogin(), is("yrodiere")); + // in offliine mode, we should not populate missing fields + assertThat(event.getRepository().getSource(), is(nullValue())); + assertThat(event.getRepository().getParent(), is(nullValue())); + + assertThat(event.getRepository().getUrl().toString(), is("https://github.com/hub4j-test-org/github-api")); + assertThat(event.getRepository().getHttpTransportUrl().toString(), + is("https://github.com/hub4j-test-org/github-api.git")); + + // Test repository populate + final GHEventPayload.Push event2 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), + GHEventPayload.Push.class); + assertThat(event2.getRepository().getUrl().toString(), is("https://github.com/hub4j-test-org/github-api")); + assertThat(event2.getRepository().getHttpTransportUrl(), + is("https://github.com/hub4j-test-org/github-api.git")); + + event2.getRepository().populate(); + + // After populate the url is fixed to point to the correct API endpoint + assertThat(event2.getRepository().getUrl().toString(), + is(mockGitHub.apiServer().baseUrl() + "/repos/hub4j-test-org/github-api")); + assertThat(event2.getRepository().getHttpTransportUrl(), + is("https://github.com/hub4j-test-org/github-api.git")); + + // ensure that root has been bound after populate + event2.getRepository().getSource().getRef("heads/main"); + event2.getRepository().getParent().getRef("heads/main"); + + // Source + final GHEventPayload.Push event3 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), + GHEventPayload.Push.class); + assertThat(event3.getRepository().getSource().getFullName(), is("hub4j/github-api")); + + // Parent + final GHEventPayload.Push event4 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), + GHEventPayload.Push.class); + assertThat(event4.getRepository().getParent().getFullName(), is("hub4j/github-api")); - GHMemberChanges changes = memberPayload.getChanges(); - assertThat(changes.getPermission().getFrom(), is(nullValue())); - assertThat(changes.getPermission().getTo(), is("admin")); } /** - * Member added with role name defined. + * Release published. * * @throws Exception * the exception */ @Test - public void member_added_role_name() throws Exception { - final GHEventPayload.Member memberPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Member.class); - - assertThat(memberPayload.getAction(), is("added")); - - assertThat(memberPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); - assertThat(memberPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-playground")); - - GHUser member = memberPayload.getMember(); - assertThat(member.getId(), is(412878L)); - assertThat(member.getLogin(), is("yrodiere")); + public void release_published() throws Exception { + final GHEventPayload.Release event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Release.class); - GHMemberChanges changes = memberPayload.getChanges(); - assertThat(changes.getPermission().getFrom(), is(nullValue())); - assertThat(changes.getPermission().getTo(), is("write")); - assertThat(changes.getRoleName().getTo(), is("maintain")); + assertThat(event.getAction(), is("published")); + assertThat(event.getSender().getLogin(), is("seregamorph")); + assertThat(event.getRepository().getName(), is("company-rest-api-framework")); + assertThat(event.getOrganization().getLogin(), is("company-group")); + assertThat(event.getInstallation(), nullValue()); + assertThat(event.getRelease().getName(), is("4.2")); + assertThat(event.getRelease().getTagName(), is("rest-api-framework-4.2")); + assertThat(event.getRelease().getBody(), is("REST-269 - unique test executions (#86) Sergey Chernov")); } /** - * Member edited. + * Repository. * * @throws Exception * the exception */ @Test - public void member_edited() throws Exception { - final GHEventPayload.Member memberPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Member.class); - - assertThat(memberPayload.getAction(), is("edited")); - - assertThat(memberPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); - assertThat(memberPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-playground")); - - GHUser member = memberPayload.getMember(); - assertThat(member.getId(), is(412878L)); - assertThat(member.getLogin(), is("yrodiere")); - - GHMemberChanges changes = memberPayload.getChanges(); - assertThat(changes.getPermission().getFrom(), is("admin")); - assertThat(changes.getPermission().getTo(), is("triage")); + public void repository() throws Exception { + final GHEventPayload.Repository event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); + assertThat(event.getAction(), is("created")); + assertThat(event.getRepository().getName(), is("new-repository")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterandthehackers")); + assertThat(event.getOrganization().getLogin(), is("baxterandthehackers")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); } /** - * Membership added. + * Repository renamed. * * @throws Exception * the exception */ @Test - public void membership_added() throws Exception { - final GHEventPayload.Membership membershipPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Membership.class); - - assertThat(membershipPayload.getAction(), is("added")); - - assertThat(membershipPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); - - GHUser member = membershipPayload.getMember(); - assertThat(member.getId(), is(1279749L)); - assertThat(member.getLogin(), is("gsmet")); - - GHTeam team = membershipPayload.getTeam(); - assertThat(team.getId(), is(9709063L)); - assertThat(team.getName(), is("New team")); - assertThat(team.getNodeId(), is("T_kwDOBNft-M4AlCYH")); - assertThat(team.getDescription(), is("Description")); - assertThat(team.getPrivacy(), is(Privacy.CLOSED)); - assertThat(team.getOrganization().getLogin(), is("gsmet-bot-playground")); + public void repository_renamed() throws Exception { + final GHEventPayload.Repository event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); + assertThat(event.getAction(), is("renamed")); + assertThat(event.getChanges().getRepository().getName().getFrom(), is("react-workshop")); + assertThat(event.getRepository().getName(), is("react-workshop-renamed")); + assertThat(event.getRepository().getOwner().getLogin(), is("EJG-Organization")); + assertThat(event.getOrganization().getLogin(), is("EJG-Organization")); + assertThat(event.getSender().getLogin(), is("eleanorgoh")); } /** - * Ping. + * Repository ownership transferred to an organization. * * @throws Exception * the exception */ @Test - public void ping() throws Exception { - final GHEventPayload.Ping event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Ping.class); - - assertThat(event.getAction(), nullValue()); - assertThat(event.getSender().getLogin(), is("seregamorph")); - assertThat(event.getRepository().getName(), is("acme-project-project")); - assertThat(event.getOrganization(), nullValue()); + public void repository_transferred_to_org() throws Exception { + final GHEventPayload.Repository event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); + assertThat(event.getAction(), is("transferred")); + assertThat(event.getChanges().getOwner().getFrom().getUser().getLogin(), is("eleanorgoh")); + assertThat(event.getChanges().getOwner().getFrom().getUser().getId(), is(66235606L)); + assertThat(event.getChanges().getOwner().getFrom().getUser().getType(), is("User")); } /** - * Projectsv 2 item archived. + * Repository ownership transferred to a user. * * @throws Exception * the exception */ @Test - public void projectsv2item_archived() throws Exception { - final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); - - assertThat(projectsV2ItemPayload.getAction(), is("archived")); - - assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083794L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().toEpochMilli(), is(1659532431000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().toEpochMilli(), is(1660086629000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt().toEpochMilli(), is(1660086629000L)); - - assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getFrom(), is(nullValue())); - assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getTo().toEpochMilli(), is(1660086629000L)); + public void repository_transferred_to_user() throws Exception { + final GHEventPayload.Repository event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); + assertThat(event.getAction(), is("transferred")); + assertThat(event.getChanges().getOwner().getFrom().getOrganization().getLogin(), is("EJG-Organization")); + assertThat(event.getChanges().getOwner().getFrom().getOrganization().getId(), is(168135412L)); + assertThat(event.getRepository().getOwner().getLogin(), is("eleanorgoh")); + assertThat(event.getRepository().getOwner().getType(), is("User")); } - // TODO implement support classes and write test - // @Test - // public void team_add() throws Exception {} - - // TODO implement support classes and write test - // @Test - // public void watch() throws Exception {} - /** - * Projectsv 2 item created. + * Status. * * @throws Exception * the exception */ @Test - public void projectsv2item_created() throws Exception { - final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); - - assertThat(projectsV2ItemPayload.getAction(), is("created")); - - assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getNodeId(), is("PVTI_lADOBNft-M4AEjBWzgB7VzY")); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getProjectNodeId(), is("PVT_kwDOBNft-M4AEjBW")); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getContentNodeId(), is("I_kwDOFOkjw85Ozz26")); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getContentType(), is(ContentType.ISSUE)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreator().getLogin(), is("gsmet")); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreator().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().toEpochMilli(), is(1659532028000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().toEpochMilli(), is(1659532028000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue())); - - assertThat(projectsV2ItemPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); - assertThat(projectsV2ItemPayload.getOrganization().getId(), is(81260024L)); - assertThat(projectsV2ItemPayload.getOrganization().getNodeId(), is("MDEyOk9yZ2FuaXphdGlvbjgxMjYwMDI0")); - - assertThat(projectsV2ItemPayload.getSender().getLogin(), is("gsmet")); - assertThat(projectsV2ItemPayload.getSender().getId(), is(1279749L)); - assertThat(projectsV2ItemPayload.getSender().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); - - assertThat(projectsV2ItemPayload.getInstallation().getId(), is(16779846L)); - assertThat(projectsV2ItemPayload.getInstallation().getNodeId(), - is("MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTY3Nzk4NDY=")); + public void status() throws Exception { + final GHEventPayload.Status event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Status.class); + assertThat(event.getContext(), is("default")); + assertThat(event.getDescription(), is("status description")); + assertThat(event.getState(), is(GHCommitState.SUCCESS)); + assertThat(event.getCommit().getSHA1(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getTargetUrl(), nullValue()); + assertThat(event.getCommit().getOwner(), sameInstance(event.getRepository())); } /** - * Projectsv 2 item edited. + * Status 2. * * @throws Exception * the exception */ @Test - public void projectsv2item_edited() throws Exception { - final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); + public void status2() throws Exception { + final GHEventPayload.Status event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Status.class); + assertThat(event.getTargetUrl(), is("https://www.wikipedia.org/")); - assertThat(projectsV2ItemPayload.getAction(), is("edited")); + assertThat(event.getCommit().getOwner(), sameInstance(event.getRepository())); + } - assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().toEpochMilli(), is(1659532028000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().toEpochMilli(), is(1659532033000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue())); + // TODO implement support classes and write test + // @Test + // public void team_add() throws Exception {} - assertThat(projectsV2ItemPayload.getChanges().getFieldValue().getFieldNodeId(), - is("PVTF_lADOBNft-M4AEjBWzgCnp5Q")); - assertThat(projectsV2ItemPayload.getChanges().getFieldValue().getFieldType(), is(FieldType.SINGLE_SELECT)); - } + // TODO implement support classes and write test + // @Test + // public void watch() throws Exception {} /** - * Projectsv 2 item reordered. + * Check run event. * * @throws Exception * the exception */ @Test - public void projectsv2item_reordered() throws Exception { - final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); + @Payload("check-run") + public void checkRunEvent() throws Exception { + final GHEventPayload.CheckRun event = GitHub.offline() + .parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), GHEventPayload.CheckRun.class); + final GHCheckRun checkRun = verifyBasicCheckRunEvent(event); + assertThat("pull body not populated offline", checkRun.getPullRequests().get(0).getBody(), nullValue()); + assertThat("using offline github", mockGitHub.getRequestCount(), equalTo(0)); + assertThat(checkRun.getPullRequests().get(0).getRepository(), sameInstance(event.getRepository())); - assertThat(projectsV2ItemPayload.getAction(), is("reordered")); + gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); + final GHEventPayload.CheckRun event2 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), + GHEventPayload.CheckRun.class); + final GHCheckRun checkRun2 = verifyBasicCheckRunEvent(event2); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083794L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().toEpochMilli(), is(1659532431000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().toEpochMilli(), is(1659532439000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue())); + int expectedRequestCount = 2; + assertThat("pull body should be populated", + checkRun2.getPullRequests().get(0).getBody(), + equalTo("This is a pretty simple change that we need to pull into main.")); + assertThat("multiple getPullRequests() calls are made, the pull is populated only once", + mockGitHub.getRequestCount(), + equalTo(expectedRequestCount)); + } - assertThat(projectsV2ItemPayload.getChanges().getPreviousProjectsV2ItemNodeId().getFrom(), - is("PVTI_lADOBNft-M4AEjBWzgB7VzY")); - assertThat(projectsV2ItemPayload.getChanges().getPreviousProjectsV2ItemNodeId().getTo(), - is("PVTI_lADOBNft-M4AEjBWzgB7VzY")); + private GHCheckRun verifyBasicCheckRunEvent(final GHEventPayload.CheckRun event) throws IOException { + assertThat(event.getRepository().getName(), is("Hello-World")); + assertThat(event.getRepository().getOwner().getLogin(), is("Codertocat")); + assertThat(event.getAction(), is("created")); + assertThat(event.getRequestedAction(), nullValue()); + + // Checks the deserialization of check_run + final GHCheckRun checkRun = event.getCheckRun(); + assertThat(checkRun.getName(), is("Octocoders-linter")); + assertThat(checkRun.getHeadSha(), is("ec26c3e57ca3a959ca5aad62de7213c562f8c821")); + assertThat(checkRun.getStatus(), is(Status.COMPLETED)); + assertThat(checkRun.getNodeId(), is("MDg6Q2hlY2tSdW4xMjg2MjAyMjg=")); + assertThat(checkRun.getExternalId(), is("")); + + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + formatter.setTimeZone(TimeZone.getTimeZone("UTC")); + assertThat(formatter.format(checkRun.getStartedAt()), is("2019-05-15T15:21:12Z")); + assertThat(formatter.format(checkRun.getCompletedAt()), is("2019-05-15T20:22:22Z")); + + assertThat(checkRun.getConclusion(), is(Conclusion.SUCCESS)); + assertThat(checkRun.getUrl().toString(), endsWith("/repos/Codertocat/Hello-World/check-runs/128620228")); + assertThat(checkRun.getHtmlUrl().toString(), + endsWith("https://github.com/Codertocat/Hello-World/runs/128620228")); + assertThat(checkRun.getDetailsUrl().toString(), is("https://octocoders.io")); + assertThat(checkRun.getApp().getId(), is(29310L)); + assertThat(checkRun.getCheckSuite().getId(), is(118578147L)); + assertThat(checkRun.getOutput().getTitle(), is("check-run output")); + assertThat(checkRun.getOutput().getSummary(), nullValue()); + assertThat(checkRun.getOutput().getText(), nullValue()); + assertThat(checkRun.getOutput().getAnnotationsCount(), is(0)); + assertThat(checkRun.getOutput().getAnnotationsUrl().toString(), + endsWith("/repos/Codertocat/Hello-World/check-runs/128620228/annotations")); + + // Checks the deserialization of sender + assertThat(event.getSender().getId(), is(21031067L)); + + assertThat(checkRun.getPullRequests(), notNullValue()); + assertThat(checkRun.getPullRequests().size(), equalTo(1)); + assertThat(checkRun.getPullRequests().get(0).getNumber(), equalTo(2)); + return checkRun; } /** - * Projectsv 2 item restored. + * Check suite event. * * @throws Exception * the exception */ @Test - public void projectsv2item_restored() throws Exception { - final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); + @Payload("check-suite") + public void checkSuiteEvent() throws Exception { + final GHEventPayload.CheckSuite event = GitHub.offline() + .parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), GHEventPayload.CheckSuite.class); + final GHCheckSuite checkSuite = verifyBasicCheckSuiteEvent(event); + assertThat("pull body not populated offline", checkSuite.getPullRequests().get(0).getBody(), nullValue()); + assertThat("using offline github", mockGitHub.getRequestCount(), equalTo(0)); + assertThat(checkSuite.getPullRequests().get(0).getRepository(), sameInstance(event.getRepository())); - assertThat(projectsV2ItemPayload.getAction(), is("restored")); + gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); + final GHEventPayload.CheckSuite event2 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), + GHEventPayload.CheckSuite.class); + final GHCheckSuite checkSuite2 = verifyBasicCheckSuiteEvent(event2); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().toEpochMilli(), is(1659532028000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().toEpochMilli(), is(1659532419000L)); - assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue())); + int expectedRequestCount = mockGitHub.isUseProxy() ? 3 : 2; + assertThat("pull body should be populated", + checkSuite2.getPullRequests().get(0).getBody(), + equalTo("This is a pretty simple change that we need to pull into main.")); + assertThat("multiple getPullRequests() calls are made, the pull is populated only once", + mockGitHub.getRequestCount(), + lessThanOrEqualTo(expectedRequestCount)); + } - assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getFrom().toEpochMilli(), is(1659532142000L)); - assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getTo(), is(nullValue())); + private GHCheckSuite verifyBasicCheckSuiteEvent(final GHEventPayload.CheckSuite event) throws IOException { + assertThat(event.getRepository().getName(), is("Hello-World")); + assertThat(event.getRepository().getOwner().getLogin(), is("Codertocat")); + assertThat(event.getAction(), is("completed")); + assertThat(event.getSender().getId(), is(21031067L)); + + // Checks the deserialization of check_suite + final GHCheckSuite checkSuite = event.getCheckSuite(); + assertThat(checkSuite.getNodeId(), is("MDEwOkNoZWNrU3VpdGUxMTg1NzgxNDc=")); + assertThat(checkSuite.getHeadBranch(), is("changes")); + assertThat(checkSuite.getHeadSha(), is("ec26c3e57ca3a959ca5aad62de7213c562f8c821")); + assertThat(checkSuite.getStatus(), is("completed")); + assertThat(checkSuite.getConclusion(), is("success")); + assertThat(checkSuite.getBefore(), is("6113728f27ae82c7b1a177c8d03f9e96e0adf246")); + assertThat(checkSuite.getAfter(), is("ec26c3e57ca3a959ca5aad62de7213c562f8c821")); + assertThat(checkSuite.getLatestCheckRunsCount(), is(1)); + assertThat(checkSuite.getCheckRunsUrl().toString(), + endsWith("/repos/Codertocat/Hello-World/check-suites/118578147/check-runs")); + assertThat(checkSuite.getHeadCommit().getMessage(), is("Update README.md")); + assertThat(checkSuite.getHeadCommit().getId(), is("ec26c3e57ca3a959ca5aad62de7213c562f8c821")); + assertThat(checkSuite.getHeadCommit().getTreeId(), is("31b122c26a97cf9af023e9ddab94a82c6e77b0ea")); + assertThat(checkSuite.getHeadCommit().getAuthor().getName(), is("Codertocat")); + assertThat(checkSuite.getHeadCommit().getCommitter().getName(), is("Codertocat")); + + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + formatter.setTimeZone(TimeZone.getTimeZone("UTC")); + assertThat(formatter.format(checkSuite.getHeadCommit().getTimestamp()), is("2019-05-15T15:20:30Z")); + + assertThat(checkSuite.getApp().getId(), is(29310L)); + + assertThat(checkSuite.getPullRequests(), notNullValue()); + assertThat(checkSuite.getPullRequests().size(), equalTo(1)); + assertThat(checkSuite.getPullRequests().get(0).getNumber(), equalTo(2)); + return checkSuite; } /** - * Public. + * Installation repositories event. * * @throws Exception * the exception */ @Test - @Payload("public") - public void public_() throws Exception { - final GHEventPayload.Public event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Public.class); - assertThat(event.getRepository().getName(), is("public-repo")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); + @Payload("installation_repositories") + public void InstallationRepositoriesEvent() throws Exception { + final GHEventPayload.InstallationRepositories event = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.InstallationRepositories.class); + + assertThat(event.getAction(), is("added")); + assertThat(event.getInstallation().getId(), is(957387L)); + assertThat(event.getInstallation().getAccount().getLogin(), is("Codertocat")); + assertThat(event.getRepositorySelection(), is("selected")); + + assertThat(event.getRepositoriesAdded().get(0).getId(), is(186853007L)); + assertThat(event.getRepositoriesAdded().get(0).getNodeId(), is("MDEwOlJlcG9zaXRvcnkxODY4NTMwMDc=")); + assertThat(event.getRepositoriesAdded().get(0).getName(), is("Space")); + assertThat(event.getRepositoriesAdded().get(0).getFullName(), is("Codertocat/Space")); + assertThat(event.getRepositoriesAdded().get(0).isPrivate(), is(false)); + + assertThat(event.getRepositoriesRemoved(), is(Collections.emptyList())); + assertThat(event.getSender().getLogin(), is("Codertocat")); } /** - * Pull request. + * Installation event. * * @throws Exception * the exception */ @Test - public void pull_request() throws Exception { - final GHEventPayload.PullRequest event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); - assertThat(event.getAction(), is("opened")); - assertThat(event.getNumber(), is(1)); - assertThat(event.getPullRequest().getNumber(), is(1)); - assertThat(event.getPullRequest().getTitle(), is("Update the README with new information")); - assertThat(event.getPullRequest().getBody(), - is("This is a pretty simple change that we need to pull into " + "main.")); - assertThat(event.getPullRequest().getUser().getLogin(), is("baxterthehacker")); - assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("baxterthehacker")); - assertThat(event.getPullRequest().getHead().getRef(), is("changes")); - assertThat(event.getPullRequest().getHead().getLabel(), is("baxterthehacker:changes")); - assertThat(event.getPullRequest().getHead().getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); - assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); - assertThat(event.getPullRequest().getBase().getRef(), is("main")); - assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:main")); - assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); - assertThat(event.getPullRequest().isMerged(), is(false)); - assertThat(event.getPullRequest().getMergeable(), nullValue()); - assertThat(event.getPullRequest().getMergeableState(), is("unknown")); - assertThat(event.getPullRequest().getMergedBy(), nullValue()); - assertThat(event.getPullRequest().getCommentsCount(), is(0)); - assertThat(event.getPullRequest().getReviewComments(), is(0)); - assertThat(event.getPullRequest().getAdditions(), is(1)); - assertThat(event.getPullRequest().getDeletions(), is(1)); - assertThat(event.getPullRequest().getChangedFiles(), is(1)); - assertThat(event.getRepository().getName(), is("public-repo")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); + @Payload("installation_created") + public void InstallationCreatedEvent() throws Exception { + final GHEventPayload.Installation event = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) + .build() + .parseEventPayload(payload.asReader(), GHEventPayload.Installation.class); - assertThat(event.getPullRequest().getRepository(), sameInstance(event.getRepository())); + assertThat(event.getAction(), is("created")); + assertThat(event.getInstallation().getId(), is(43898337L)); + assertThat(event.getInstallation().getAccount().getLogin(), is("CronFire")); + + assertThat(event.getRepositories().isEmpty(), is(false)); + assertThat(event.getRepositories().get(0).getId(), is(1296269L)); + assertThat(event.getRawRepositories().isEmpty(), is(false)); + assertThat(event.getRawRepositories().get(0).getId(), is(1296269L)); + + assertThat(event.getSender().getLogin(), is("Haarolean")); } /** - * Pull request edited base. + * Installation event. * * @throws Exception * the exception */ @Test - public void pull_request_edited_base() throws Exception { - final GHEventPayload.PullRequest event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); + @Payload("installation_deleted") + public void InstallationDeletedEvent() throws Exception { + final GHEventPayload.Installation event = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) + .build() + .parseEventPayload(payload.asReader(), GHEventPayload.Installation.class); - assertThat(event.getAction(), is("edited")); - assertThat(event.getChanges().getTitle(), nullValue()); - assertThat(event.getPullRequest().getTitle(), is("REST-276 - easy-random")); - assertThat(event.getChanges().getBase().getRef().getFrom(), is("develop")); - assertThat(event.getChanges().getBase().getSha().getFrom(), is("4b0f3b9fd582b071652ccfccd10bfc8c143cff96")); - assertThat(event.getPullRequest().getBase().getRef(), is("4.3")); - assertThat(event.getPullRequest().getBody(), startsWith("**JIRA Ticket URL:**")); - assertThat(event.getChanges().getBody(), nullValue()); - } + assertThat(event.getAction(), is("deleted")); + assertThat(event.getInstallation().getId(), is(2L)); + assertThat(event.getInstallation().getAccount().getLogin(), is("octocat")); - /** - * Pull request edited title. - * - * @throws Exception - * the exception - */ - @Test - public void pull_request_edited_title() throws Exception { - final GHEventPayload.PullRequest event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); + assertThrows(IllegalStateException.class, () -> event.getRepositories().isEmpty()); + assertThat(event.getRawRepositories().isEmpty(), is(false)); + assertThat(event.getRawRepositories().get(0).getId(), is(1296269L)); + assertThat(event.getRawRepositories().get(0).getNodeId(), is("MDEwOlJlcG9zaXRvcnkxMjk2MjY5")); + assertThat(event.getRawRepositories().get(0).getName(), is("Hello-World")); + assertThat(event.getRawRepositories().get(0).getFullName(), is("octocat/Hello-World")); + assertThat(event.getRawRepositories().get(0).isPrivate(), is(false)); - assertThat(event.getAction(), is("edited")); - assertThat(event.getChanges().getTitle().getFrom(), is("REST-276 - easy-random")); - assertThat(event.getPullRequest().getTitle(), is("REST-276 - easy-random 4.3.0")); - assertThat(event.getChanges().getBase(), nullValue()); - assertThat(event.getPullRequest().getBase().getRef(), is("4.3")); - assertThat(event.getPullRequest().getBody(), startsWith("**JIRA Ticket URL:**")); - assertThat(event.getChanges().getBody(), nullValue()); + assertThat(event.getSender().getLogin(), is("octocat")); } /** - * Pull request labeled. + * Workflow dispatch. * * @throws Exception * the exception */ @Test - public void pull_request_labeled() throws Exception { - final GHEventPayload.PullRequest event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); - assertThat(event.getAction(), is("labeled")); - assertThat(event.getNumber(), is(79)); - assertThat(event.getPullRequest().getNumber(), is(79)); - assertThat(event.getPullRequest().getTitle(), is("Base POJO test enhancement")); - assertThat(event.getPullRequest().getBody(), - is("This is a pretty simple change that we need to pull into develop.")); - assertThat(event.getPullRequest().getUser().getLogin(), is("seregamorph")); - assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("trilogy-group")); - assertThat(event.getPullRequest().getHead().getRef(), is("changes")); - assertThat(event.getPullRequest().getHead().getLabel(), is("trilogy-group:changes")); - assertThat(event.getPullRequest().getHead().getSha(), is("4b91e3a970fb967fb7be4d52e0969f8e3fb063d0")); - assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("trilogy-group")); - assertThat(event.getPullRequest().getBase().getRef(), is("3.10")); - assertThat(event.getPullRequest().getBase().getLabel(), is("trilogy-group:3.10")); - assertThat(event.getPullRequest().getBase().getSha(), is("7a735f17d686c6a1fc7df5b9d395e5863868f364")); - assertThat(event.getPullRequest().isMerged(), is(false)); - assertThat(event.getPullRequest().getMergeable(), is(true)); - assertThat(event.getPullRequest().getMergeableState(), is("draft")); - assertThat(event.getPullRequest().getMergedBy(), nullValue()); - assertThat(event.getPullRequest().getCommentsCount(), is(1)); - assertThat(event.getPullRequest().getReviewComments(), is(14)); - assertThat(event.getPullRequest().getAdditions(), is(137)); - assertThat(event.getPullRequest().getDeletions(), is(81)); - assertThat(event.getPullRequest().getChangedFiles(), is(22)); - assertThat(event.getPullRequest().getLabels().iterator().next().getName(), is("Ready for Review")); - assertThat(event.getRepository().getName(), is("trilogy-rest-api-framework")); - assertThat(event.getRepository().getOwner().getLogin(), is("trilogy-group")); - assertThat(event.getSender().getLogin(), is("schernov-xo")); - assertThat(event.getLabel().getUrl(), - is("https://api.github.com/repos/trilogy-group/trilogy-rest-api-framework/labels/rest%20api")); - assertThat(event.getLabel().getName(), is("rest api")); - assertThat(event.getLabel().getColor(), is("fef2c0")); - assertThat(event.getLabel().getDescription(), is("REST API pull request")); - assertThat(event.getOrganization().getLogin(), is("trilogy-group")); + public void workflow_dispatch() throws Exception { + final GHEventPayload.WorkflowDispatch workflowDispatchPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowDispatch.class); + + assertThat(workflowDispatchPayload.getRef(), is("refs/heads/main")); + assertThat(workflowDispatchPayload.getAction(), is(nullValue())); + assertThat(workflowDispatchPayload.getWorkflow(), is(".github/workflows/main.yml")); + assertThat(workflowDispatchPayload.getInputs(), aMapWithSize(1)); + assertThat(workflowDispatchPayload.getInputs().keySet(), contains("logLevel")); + assertThat(workflowDispatchPayload.getInputs().values(), contains("warning")); + assertThat(workflowDispatchPayload.getRepository().getName(), is("quarkus-bot-java-playground")); + assertThat(workflowDispatchPayload.getSender().getLogin(), is("gsmet")); } /** - * Pull request review. + * Workflow run. * * @throws Exception * the exception */ @Test - public void pull_request_review() throws Exception { - final GHEventPayload.PullRequestReview event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReview.class); - assertThat(event.getAction(), is("submitted")); - - assertThat(event.getReview().getId(), is(2626884L)); - assertThat(event.getReview().getBody(), is("Looks great!\n")); - assertThat(event.getReview().getState(), is(GHPullRequestReviewState.APPROVED)); - - assertThat(event.getPullRequest().getNumber(), is(8)); - assertThat(event.getPullRequest().getTitle(), is("Add a README description")); - assertThat(event.getPullRequest().getBody(), is("Just a few more details")); - assertThat(event.getReview().getHtmlUrl(), - hasToString("https://github.com/baxterthehacker/public-repo/pull/8#pullrequestreview-2626884")); - assertThat(event.getPullRequest().getUser().getLogin(), is("skalnik")); - assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("skalnik")); - assertThat(event.getPullRequest().getHead().getRef(), is("patch-2")); - assertThat(event.getPullRequest().getHead().getLabel(), is("skalnik:patch-2")); - assertThat(event.getPullRequest().getHead().getSha(), is("b7a1f9c27caa4e03c14a88feb56e2d4f7500aa63")); - assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); - assertThat(event.getPullRequest().getBase().getRef(), is("main")); - assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:main")); - assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + public void workflow_run() throws Exception { + final GHEventPayload.WorkflowRun workflowRunPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowRun.class); - assertThat(event.getRepository().getName(), is("public-repo")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(workflowRunPayload.getAction(), is("completed")); + assertThat(workflowRunPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(workflowRunPayload.getSender().getLogin(), is("gsmet")); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); + GHWorkflow workflow = workflowRunPayload.getWorkflow(); + assertThat(workflow.getId(), is(7087581L)); + assertThat(workflow.getName(), is("CI")); + assertThat(workflow.getPath(), is(".github/workflows/main.yml")); + assertThat(workflow.getState(), is("active")); + assertThat(workflow.getUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/workflows/7087581")); + assertThat(workflow.getHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/blob/main/.github/workflows/main.yml")); + assertThat(workflow.getBadgeUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/workflows/CI/badge.svg")); - assertThat(event.getPullRequest().getRepository(), sameInstance(event.getRepository())); - assertThat(event.getReview().getParent(), sameInstance(event.getPullRequest())); + GHWorkflowRun workflowRun = workflowRunPayload.getWorkflowRun(); + assertThat(workflowRun.getId(), is(680604745L)); + assertThat(workflowRun.getName(), is("CI")); + assertThat(workflowRun.getHeadBranch(), is("main")); + assertThat(workflowRun.getDisplayTitle(), is("its-display-title")); + assertThat(workflowRun.getHeadSha(), is("dbea8d8b6ed2cf764dfd84a215f3f9040b3d4423")); + assertThat(workflowRun.getRunNumber(), is(6L)); + assertThat(workflowRun.getEvent(), is(GHEvent.WORKFLOW_DISPATCH)); + assertThat(workflowRun.getStatus(), is(GHWorkflowRun.Status.COMPLETED)); + assertThat(workflowRun.getConclusion(), is(GHWorkflowRun.Conclusion.SUCCESS)); + assertThat(workflowRun.getWorkflowId(), is(7087581L)); + assertThat(workflowRun.getUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745")); + assertThat(workflowRun.getHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/actions/runs/680604745")); + assertThat(workflowRun.getJobsUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/jobs")); + assertThat(workflowRun.getLogsUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/logs")); + assertThat(workflowRun.getCheckSuiteUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/check-suites/2327154397")); + assertThat(workflowRun.getArtifactsUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/artifacts")); + assertThat(workflowRun.getCancelUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/cancel")); + assertThat(workflowRun.getRerunUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/rerun")); + assertThat(workflowRun.getWorkflowUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/workflows/7087581")); + assertThat(workflowRun.getCreatedAt().getTime(), is(1616524526000L)); + assertThat(workflowRun.getUpdatedAt().getTime(), is(1616524543000L)); + assertThat(workflowRun.getRunAttempt(), is(1L)); + assertThat(workflowRun.getRunStartedAt().getTime(), is(1616524526000L)); + assertThat(workflowRun.getHeadCommit().getId(), is("dbea8d8b6ed2cf764dfd84a215f3f9040b3d4423")); + assertThat(workflowRun.getHeadCommit().getTreeId(), is("b17089e6a2574ec1002566fe980923e62dce3026")); + assertThat(workflowRun.getHeadCommit().getMessage(), is("Update main.yml")); + assertThat(workflowRun.getHeadCommit().getTimestamp().getTime(), is(1616523390000L)); + assertThat(workflowRun.getHeadCommit().getAuthor().getName(), is("Guillaume Smet")); + assertThat(workflowRun.getHeadCommit().getAuthor().getEmail(), is("guillaume.smet@gmail.com")); + assertThat(workflowRun.getHeadCommit().getCommitter().getName(), is("GitHub")); + assertThat(workflowRun.getHeadCommit().getCommitter().getEmail(), is("noreply@github.com")); + assertThat(workflowRun.getHeadRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(workflowRun.getRepository(), sameInstance(workflowRunPayload.getRepository())); } /** - * Pull request review comment. + * Workflow run pull request. * * @throws Exception * the exception */ @Test - public void pull_request_review_comment() throws Exception { - final GHEventPayload.PullRequestReviewComment event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReviewComment.class); - assertThat(event.getAction(), is("created")); - - assertThat(event.getComment().getBody(), is("Maybe you should use more emojji on this line.")); - - assertThat(event.getPullRequest().getNumber(), is(1)); - assertThat(event.getPullRequest().getTitle(), is("Update the README with new information")); - assertThat(event.getPullRequest().getBody(), - is("This is a pretty simple change that we need to pull into main.")); - assertThat(event.getPullRequest().getUser().getLogin(), is("baxterthehacker")); - assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("baxterthehacker")); - assertThat(event.getPullRequest().getHead().getRef(), is("changes")); - assertThat(event.getPullRequest().getHead().getLabel(), is("baxterthehacker:changes")); - assertThat(event.getPullRequest().getHead().getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); - assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); - assertThat(event.getPullRequest().getBase().getRef(), is("main")); - assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:main")); - assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); - - assertThat(event.getRepository().getName(), is("public-repo")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + public void workflow_run_pull_request() throws Exception { + final GHEventPayload.WorkflowRun workflowRunPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowRun.class); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); + List pullRequests = workflowRunPayload.getWorkflowRun().getPullRequests(); + assertThat(pullRequests.size(), is(1)); - assertThat(event.getPullRequest().getRepository(), sameInstance(event.getRepository())); - assertThat(event.getComment().getParent(), sameInstance(event.getPullRequest())); + GHPullRequest pullRequest = pullRequests.get(0); + assertThat(pullRequest.getId(), is(599098265L)); + assertThat(pullRequest.getRepository(), sameInstance(workflowRunPayload.getRepository())); } /** - * Pull request review comment edited. + * Workflow run other repository. * * @throws Exception * the exception */ @Test - public void pull_request_review_comment_edited() throws Exception { - final GHEventPayload.PullRequestReviewComment event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReviewComment.class); - assertThat(event.getAction(), is("edited")); - assertThat(event.getPullRequest().getNumber(), is(4)); - assertThat(event.getComment().getBody(), is("This is the pull request review comment AFTER edit.")); - assertThat(event.getChanges().getBody().getFrom(), is("This is the pull request review comment BEFORE edit.")); + public void workflow_run_other_repository() throws Exception { + final GHEventPayload.WorkflowRun workflowRunPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowRun.class); + GHWorkflowRun workflowRun = workflowRunPayload.getWorkflowRun(); + + assertThat(workflowRunPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(workflowRun.getHeadRepository().getFullName(), + is("gsmet-bot-playground/quarkus-bot-java-playground")); + assertThat(workflowRun.getRepository(), sameInstance(workflowRunPayload.getRepository())); + assertThat(workflowRunPayload.getWorkflow().getRepository(), sameInstance(workflowRunPayload.getRepository())); } /** - * Push. + * Workflow job. * * @throws Exception * the exception */ @Test - public void push() throws Exception { - final GHEventPayload.Push event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Push.class); - assertThat(event.getRef(), is("refs/heads/changes")); - assertThat(event.getBefore(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); - assertThat(event.getHead(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); - assertThat(event.isCreated(), is(false)); - assertThat(event.isDeleted(), is(false)); - assertThat(event.isForced(), is(false)); - assertThat(event.getCommits().size(), is(1)); - assertThat(event.getCommits().get(0).getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); - assertThat(event.getCommits().get(0).getAuthor().getEmail(), is("baxterthehacker@users.noreply.github.com")); - assertThat(event.getCommits().get(0).getAuthor().getUsername(), is("baxterthehacker")); - assertThat(event.getCommits().get(0).getCommitter().getEmail(), is("baxterthehacker@users.noreply.github.com")); - assertThat(event.getCommits().get(0).getCommitter().getUsername(), is("baxterthehacker")); - assertThat(event.getCommits().get(0).getAdded().size(), is(0)); - assertThat(event.getCommits().get(0).getRemoved().size(), is(0)); - assertThat(event.getCommits().get(0).getModified().size(), is(1)); - assertThat(event.getCommits().get(0).getModified().get(0), is("README.md")); + public void workflow_job() throws Exception { + final GHEventPayload.WorkflowJob workflowJobPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowJob.class); - assertThat(event.getHeadCommit().getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); - assertThat(event.getHeadCommit().getAuthor().getEmail(), is("baxterthehacker@users.noreply.github.com")); - assertThat(event.getHeadCommit().getAuthor().getUsername(), is("baxterthehacker")); - assertThat(event.getHeadCommit().getCommitter().getEmail(), is("baxterthehacker@users.noreply.github.com")); - assertThat(event.getHeadCommit().getCommitter().getUsername(), is("baxterthehacker")); - assertThat(event.getHeadCommit().getAdded().size(), is(0)); - assertThat(event.getHeadCommit().getRemoved().size(), is(0)); - assertThat(event.getHeadCommit().getModified().size(), is(1)); - assertThat(event.getHeadCommit().getModified().get(0), is("README.md")); - assertThat(event.getHeadCommit().getMessage(), is("Update README.md")); + assertThat(workflowJobPayload.getAction(), is("completed")); + assertThat(workflowJobPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(workflowJobPayload.getSender().getLogin(), is("gsmet")); - assertThat(GitHubClient.printInstant(event.getCommits().get(0).getTimestamp()), is("2015-05-05T23:40:15Z")); - assertThat(event.getRepository().getName(), is("public-repo")); - assertThat(event.getRepository().getOwnerName(), is("baxterthehacker")); - assertThat(event.getRepository().getUrl().toExternalForm(), - is("https://github.com/baxterthehacker/public-repo")); - assertThat(event.getPusher().getName(), is("baxterthehacker")); - assertThat(event.getPusher().getEmail(), is("baxterthehacker@users.noreply.github.com")); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); - assertThat(event.getCompare(), - is("https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f")); + GHWorkflowJob workflowJob = workflowJobPayload.getWorkflowJob(); + assertThat(workflowJob.getId(), is(6653410527L)); + assertThat(workflowJob.getRunId(), is(2408553341L)); + assertThat(workflowJob.getRunAttempt(), is(1)); + assertThat(workflowJob.getUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/jobs/6653410527")); + assertThat(workflowJob.getHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/runs/6653410527?check_suite_focus=true")); + assertThat(workflowJob.getNodeId(), is("CR_kwDOEq3cwc8AAAABjJL83w")); + assertThat(workflowJob.getHeadSha(), is("5dd2dadfbdc2a722c08a8ad42ae4e26e3e731042")); + assertThat(workflowJob.getStatus(), is(GHWorkflowRun.Status.COMPLETED)); + assertThat(workflowJob.getConclusion(), is(GHWorkflowRun.Conclusion.FAILURE)); + assertThat(workflowJob.getStartedAt().getTime(), is(1653908125000L)); + assertThat(workflowJob.getCompletedAt().getTime(), is(1653908157000L)); + assertThat(workflowJob.getName(), is("JVM Tests - JDK JDK16")); + assertThat(workflowJob.getSteps(), + contains(hasProperty("name", is("Set up job")), + hasProperty("name", is("Run actions/checkout@v2")), + hasProperty("name", is("Build with Maven")), + hasProperty("name", is("Post Run actions/checkout@v2")), + hasProperty("name", is("Complete job")))); + assertThat(workflowJob.getCheckRunUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/check-runs/6653410527")); } /** - * Push to fork. + * Label created. * * @throws Exception * the exception */ @Test - @Payload("push.fork") - public void pushToFork() throws Exception { - gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); + public void label_created() throws Exception { + final GHEventPayload.Label labelPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Label.class); + GHLabel label = labelPayload.getLabel(); - final GHEventPayload.Push event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Push.class); - assertThat(event.getRef(), is("refs/heads/changes")); - assertThat(event.getBefore(), is("85c44b352958bf6d81b74ab8b21920f1d313a287")); - assertThat(event.getHead(), is("1393706f1364742defbc28ba459082630ca979af")); - assertThat(event.isCreated(), is(false)); - assertThat(event.isDeleted(), is(false)); - assertThat(event.isForced(), is(false)); - assertThat(event.getCommits().size(), is(1)); - assertThat(event.getCommits().get(0).getSha(), is("1393706f1364742defbc28ba459082630ca979af")); - assertThat(event.getCommits().get(0).getAuthor().getEmail(), is("bitwiseman@gmail.com")); - assertThat(event.getCommits().get(0).getCommitter().getEmail(), is("bitwiseman@gmail.com")); - assertThat(event.getCommits().get(0).getAdded().size(), is(6)); - assertThat(event.getCommits().get(0).getRemoved().size(), is(0)); - assertThat(event.getCommits().get(0).getModified().size(), is(2)); - assertThat(event.getCommits().get(0).getModified().get(0), - is("src/main/java/org/kohsuke/github/GHLicense.java")); - assertThat(event.getRepository().getName(), is("github-api")); - assertThat(event.getRepository().getOwnerName(), is("hub4j-test-org")); - assertThat(event.getRepository().getUrl().toExternalForm(), is("https://github.com/hub4j-test-org/github-api")); - assertThat(event.getPusher().getName(), is("bitwiseman")); - assertThat(event.getPusher().getEmail(), is("bitwiseman@gmail.com")); - assertThat(event.getSender().getLogin(), is("bitwiseman")); + assertThat(labelPayload.getAction(), is("created")); + assertThat(labelPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(label.getId(), is(2901546662L)); + assertThat(label.getNodeId(), is("MDU6TGFiZWwyOTAxNTQ2NjYy")); + assertThat(label.getName(), is("new-label")); + assertThat(label.getColor(), is("f9d0c4")); + assertThat(label.isDefault(), is(false)); + assertThat(label.getDescription(), is("description")); + } - assertThat(event.getRepository().isFork(), is(true)); + /** + * Label edited. + * + * @throws Exception + * the exception + */ + @Test + public void label_edited() throws Exception { + final GHEventPayload.Label labelPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Label.class); + GHLabel label = labelPayload.getLabel(); - // in offliine mode, we should not populate missing fields - assertThat(event.getRepository().getSource(), is(nullValue())); - assertThat(event.getRepository().getParent(), is(nullValue())); + assertThat(labelPayload.getAction(), is("edited")); + assertThat(labelPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(label.getId(), is(2901546662L)); + assertThat(label.getNodeId(), is("MDU6TGFiZWwyOTAxNTQ2NjYy")); + assertThat(label.getName(), is("new-label-updated")); + assertThat(label.getColor(), is("4AE686")); + assertThat(label.isDefault(), is(false)); + assertThat(label.getDescription(), is("description")); - assertThat(event.getRepository().getUrl().toString(), is("https://github.com/hub4j-test-org/github-api")); - assertThat(event.getRepository().getHttpTransportUrl().toString(), - is("https://github.com/hub4j-test-org/github-api.git")); + assertThat(labelPayload.getChanges().getName().getFrom(), is("new-label")); + assertThat(labelPayload.getChanges().getColor().getFrom(), is("f9d0c4")); + } - // Test repository populate - final GHEventPayload.Push event2 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), - GHEventPayload.Push.class); - assertThat(event2.getRepository().getUrl().toString(), is("https://github.com/hub4j-test-org/github-api")); - assertThat(event2.getRepository().getHttpTransportUrl(), - is("https://github.com/hub4j-test-org/github-api.git")); + /** + * Label deleted. + * + * @throws Exception + * the exception + */ + @Test + public void label_deleted() throws Exception { + GHEventPayload.Label labelPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Label.class); + GHLabel label = labelPayload.getLabel(); - event2.getRepository().populate(); + assertThat(labelPayload.getAction(), is("deleted")); + assertThat(labelPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(label.getId(), is(2901546662L)); + assertThat(label.getNodeId(), is("MDU6TGFiZWwyOTAxNTQ2NjYy")); + assertThat(label.getName(), is("new-label-updated")); + assertThat(label.getColor(), is("4AE686")); + assertThat(label.isDefault(), is(false)); + assertThat(label.getDescription(), is("description")); + } + + /** + * Discussion created. + * + * @throws Exception + * the exception + */ + @Test + public void discussion_created() throws Exception { + final GHEventPayload.Discussion discussionPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Discussion.class); + + assertThat(discussionPayload.getAction(), is("created")); + assertThat(discussionPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(discussionPayload.getSender().getLogin(), is("gsmet")); + + GHRepositoryDiscussion discussion = discussionPayload.getDiscussion(); + + GHRepositoryDiscussion.Category category = discussion.getCategory(); + + assertThat(category.getId(), is(33522033L)); + assertThat(category.getNodeId(), is("DIC_kwDOEq3cwc4B_4Fx")); + assertThat(category.getEmoji(), is(":pray:")); + assertThat(category.getName(), is("Q&A")); + assertThat(category.getDescription(), is("Ask the community for help")); + assertThat(category.getCreatedAt().getTime(), is(1636991431000L)); + assertThat(category.getUpdatedAt().getTime(), is(1636991431000L)); + assertThat(category.getSlug(), is("q-a")); + assertThat(category.isAnswerable(), is(true)); + + assertThat(discussion.getAnswerHtmlUrl(), is(nullValue())); + assertThat(discussion.getAnswerChosenAt(), is(nullValue())); + assertThat(discussion.getAnswerChosenBy(), is(nullValue())); + + assertThat(discussion.getHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/78")); + assertThat(discussion.getId(), is(3698909L)); + assertThat(discussion.getNodeId(), is("D_kwDOEq3cwc4AOHDd")); + assertThat(discussion.getNumber(), is(78)); + assertThat(discussion.getTitle(), is("Title of discussion")); + + assertThat(discussion.getUser().getLogin(), is("gsmet")); + assertThat(discussion.getUser().getId(), is(1279749L)); + assertThat(discussion.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); + + assertThat(discussion.getState(), is(GHRepositoryDiscussion.State.OPEN)); + assertThat(discussion.isLocked(), is(false)); + assertThat(discussion.getComments(), is(0)); + assertThat(discussion.getCreatedAt().getTime(), is(1637584949000L)); + assertThat(discussion.getUpdatedAt().getTime(), is(1637584949000L)); + assertThat(discussion.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); + assertThat(discussion.getActiveLockReason(), is(nullValue())); + assertThat(discussion.getBody(), is("Body of discussion.")); + } + + /** + * Discussion answered. + * + * @throws Exception + * the exception + */ + @Test + public void discussion_answered() throws Exception { + final GHEventPayload.Discussion discussionPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Discussion.class); + + assertThat(discussionPayload.getAction(), is("answered")); + assertThat(discussionPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(discussionPayload.getSender().getLogin(), is("gsmet")); + + GHRepositoryDiscussion discussion = discussionPayload.getDiscussion(); + + GHRepositoryDiscussion.Category category = discussion.getCategory(); + + assertThat(category.getId(), is(33522033L)); + assertThat(category.getNodeId(), is("DIC_kwDOEq3cwc4B_4Fx")); + assertThat(category.getEmoji(), is(":pray:")); + assertThat(category.getName(), is("Q&A")); + assertThat(category.getDescription(), is("Ask the community for help")); + assertThat(category.getCreatedAt().getTime(), is(1636991431000L)); + assertThat(category.getUpdatedAt().getTime(), is(1636991431000L)); + assertThat(category.getSlug(), is("q-a")); + assertThat(category.isAnswerable(), is(true)); + + assertThat(discussion.getAnswerHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/78#discussioncomment-1681242")); + assertThat(discussion.getAnswerChosenAt().getTime(), is(1637585047000L)); + assertThat(discussion.getAnswerChosenBy().getLogin(), is("gsmet")); + + assertThat(discussion.getHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/78")); + assertThat(discussion.getId(), is(3698909L)); + assertThat(discussion.getNodeId(), is("D_kwDOEq3cwc4AOHDd")); + assertThat(discussion.getNumber(), is(78)); + assertThat(discussion.getTitle(), is("Title of discussion")); + + assertThat(discussion.getUser().getLogin(), is("gsmet")); + assertThat(discussion.getUser().getId(), is(1279749L)); + assertThat(discussion.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); + + assertThat(discussion.getState(), is(GHRepositoryDiscussion.State.OPEN)); + assertThat(discussion.isLocked(), is(false)); + assertThat(discussion.getComments(), is(1)); + assertThat(discussion.getCreatedAt().getTime(), is(1637584949000L)); + assertThat(discussion.getUpdatedAt().getTime(), is(1637585047000L)); + assertThat(discussion.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); + assertThat(discussion.getActiveLockReason(), is(nullValue())); + assertThat(discussion.getBody(), is("Body of discussion.")); + } + + /** + * Discussion labeled. + * + * @throws Exception + * the exception + */ + @Test + public void discussion_labeled() throws Exception { + final GHEventPayload.Discussion discussionPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Discussion.class); + + assertThat(discussionPayload.getAction(), is("labeled")); + assertThat(discussionPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(discussionPayload.getSender().getLogin(), is("gsmet")); + + GHRepositoryDiscussion discussion = discussionPayload.getDiscussion(); + + GHRepositoryDiscussion.Category category = discussion.getCategory(); + + assertThat(category.getId(), is(33522033L)); + assertThat(category.getNodeId(), is("DIC_kwDOEq3cwc4B_4Fx")); + assertThat(category.getEmoji(), is(":pray:")); + assertThat(category.getName(), is("Q&A")); + assertThat(category.getDescription(), is("Ask the community for help")); + assertThat(category.getCreatedAt().getTime(), is(1636991431000L)); + assertThat(category.getUpdatedAt().getTime(), is(1636991431000L)); + assertThat(category.getSlug(), is("q-a")); + assertThat(category.isAnswerable(), is(true)); + + assertThat(discussion.getAnswerHtmlUrl(), is(nullValue())); + assertThat(discussion.getAnswerChosenAt(), is(nullValue())); + assertThat(discussion.getAnswerChosenBy(), is(nullValue())); + + assertThat(discussion.getHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/78")); + assertThat(discussion.getId(), is(3698909L)); + assertThat(discussion.getNodeId(), is("D_kwDOEq3cwc4AOHDd")); + assertThat(discussion.getNumber(), is(78)); + assertThat(discussion.getTitle(), is("Title of discussion")); + + assertThat(discussion.getUser().getLogin(), is("gsmet")); + assertThat(discussion.getUser().getId(), is(1279749L)); + assertThat(discussion.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); + + assertThat(discussion.getState(), is(GHRepositoryDiscussion.State.OPEN)); + assertThat(discussion.isLocked(), is(false)); + assertThat(discussion.getComments(), is(0)); + assertThat(discussion.getCreatedAt().getTime(), is(1637584949000L)); + assertThat(discussion.getUpdatedAt().getTime(), is(1637584961000L)); + assertThat(discussion.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); + assertThat(discussion.getActiveLockReason(), is(nullValue())); + assertThat(discussion.getBody(), is("Body of discussion.")); + + GHLabel label = discussionPayload.getLabel(); + assertThat(label.getId(), is(2543373314L)); + assertThat(label.getNodeId(), is("MDU6TGFiZWwyNTQzMzczMzE0")); + assertThat(label.getUrl().toString(), + is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/labels/area/hibernate-validator")); + assertThat(label.getName(), is("area/hibernate-validator")); + assertThat(label.getColor(), is("ededed")); + assertThat(label.isDefault(), is(false)); + assertThat(label.getDescription(), is(nullValue())); + } + + /** + * Discussion comment created. + * + * @throws Exception + * the exception + */ + @Test + public void discussion_comment_created() throws Exception { + final GHEventPayload.DiscussionComment discussionCommentPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.DiscussionComment.class); + + assertThat(discussionCommentPayload.getAction(), is("created")); + assertThat(discussionCommentPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(discussionCommentPayload.getSender().getLogin(), is("gsmet")); + + GHRepositoryDiscussion discussion = discussionCommentPayload.getDiscussion(); + + GHRepositoryDiscussion.Category category = discussion.getCategory(); + + assertThat(category.getId(), is(33522033L)); + assertThat(category.getNodeId(), is("DIC_kwDOEq3cwc4B_4Fx")); + assertThat(category.getEmoji(), is(":pray:")); + assertThat(category.getName(), is("Q&A")); + assertThat(category.getDescription(), is("Ask the community for help")); + assertThat(category.getCreatedAt().getTime(), is(1636991431000L)); + assertThat(category.getUpdatedAt().getTime(), is(1636991431000L)); + assertThat(category.getSlug(), is("q-a")); + assertThat(category.isAnswerable(), is(true)); + + assertThat(discussion.getAnswerHtmlUrl(), is(nullValue())); + assertThat(discussion.getAnswerChosenAt(), is(nullValue())); + assertThat(discussion.getAnswerChosenBy(), is(nullValue())); + + assertThat(discussion.getHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/162")); + assertThat(discussion.getId(), is(6090566L)); + assertThat(discussion.getNodeId(), is("D_kwDOEq3cwc4AXO9G")); + assertThat(discussion.getNumber(), is(162)); + assertThat(discussion.getTitle(), is("New test question")); + + assertThat(discussion.getUser().getLogin(), is("gsmet")); + assertThat(discussion.getUser().getId(), is(1279749L)); + assertThat(discussion.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); + + assertThat(discussion.getState(), is(GHRepositoryDiscussion.State.OPEN)); + assertThat(discussion.isLocked(), is(false)); + assertThat(discussion.getComments(), is(1)); + assertThat(discussion.getCreatedAt().getTime(), is(1705586390000L)); + assertThat(discussion.getUpdatedAt().getTime(), is(1705586399000L)); + assertThat(discussion.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); + assertThat(discussion.getActiveLockReason(), is(nullValue())); + assertThat(discussion.getBody(), is("Test question")); + + GHRepositoryDiscussionComment comment = discussionCommentPayload.getComment(); + + assertThat(comment.getHtmlUrl().toString(), + is("https://github.com/gsmet/quarkus-bot-java-playground/discussions/162#discussioncomment-8169669")); + assertThat(comment.getId(), is(8169669L)); + assertThat(comment.getNodeId(), is("DC_kwDOEq3cwc4AfKjF")); + assertThat(comment.getAuthorAssociation(), is(GHCommentAuthorAssociation.OWNER)); + assertThat(comment.getCreatedAt().getTime(), is(1705586398000L)); + assertThat(comment.getUpdatedAt().getTime(), is(1705586399000L)); + assertThat(comment.getBody(), is("Test comment.")); + assertThat(comment.getUser().getLogin(), is("gsmet")); + assertThat(comment.getUser().getId(), is(1279749L)); + assertThat(comment.getUser().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); + assertThat(comment.getParentId(), is(nullValue())); + assertThat(comment.getChildCommentCount(), is(0)); + } + + /** + * Starred. + * + * @throws Exception + * the exception + */ + @Test + public void starred() throws Exception { + final GHEventPayload.Star starPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Star.class); + + assertThat(starPayload.getAction(), is("created")); + assertThat(starPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); + assertThat(starPayload.getSender().getLogin(), is("gsmet")); + assertThat(starPayload.getStarredAt().getTime(), is(1654017876000L)); + } + + /** + * Projectsv 2 item created. + * + * @throws Exception + * the exception + */ + @Test + public void projectsv2item_created() throws Exception { + final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); - // After populate the url is fixed to point to the correct API endpoint - assertThat(event2.getRepository().getUrl().toString(), - is(mockGitHub.apiServer().baseUrl() + "/repos/hub4j-test-org/github-api")); - assertThat(event2.getRepository().getHttpTransportUrl(), - is("https://github.com/hub4j-test-org/github-api.git")); + assertThat(projectsV2ItemPayload.getAction(), is("created")); - // ensure that root has been bound after populate - event2.getRepository().getSource().getRef("heads/main"); - event2.getRepository().getParent().getRef("heads/main"); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getNodeId(), is("PVTI_lADOBNft-M4AEjBWzgB7VzY")); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getProjectNodeId(), is("PVT_kwDOBNft-M4AEjBW")); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getContentNodeId(), is("I_kwDOFOkjw85Ozz26")); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getContentType(), is(ContentType.ISSUE)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreator().getLogin(), is("gsmet")); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreator().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532028000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1659532028000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue())); - // Source - final GHEventPayload.Push event3 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), - GHEventPayload.Push.class); - assertThat(event3.getRepository().getSource().getFullName(), is("hub4j/github-api")); + assertThat(projectsV2ItemPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); + assertThat(projectsV2ItemPayload.getOrganization().getId(), is(81260024L)); + assertThat(projectsV2ItemPayload.getOrganization().getNodeId(), is("MDEyOk9yZ2FuaXphdGlvbjgxMjYwMDI0")); - // Parent - final GHEventPayload.Push event4 = gitHub.parseEventPayload(payload.asReader(mockGitHub::mapToMockGitHub), - GHEventPayload.Push.class); - assertThat(event4.getRepository().getParent().getFullName(), is("hub4j/github-api")); + assertThat(projectsV2ItemPayload.getSender().getLogin(), is("gsmet")); + assertThat(projectsV2ItemPayload.getSender().getId(), is(1279749L)); + assertThat(projectsV2ItemPayload.getSender().getNodeId(), is("MDQ6VXNlcjEyNzk3NDk=")); + assertThat(projectsV2ItemPayload.getInstallation().getId(), is(16779846L)); + assertThat(projectsV2ItemPayload.getInstallation().getNodeId(), + is("MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMTY3Nzk4NDY=")); } /** - * Release published. + * Projectsv 2 item edited. * * @throws Exception * the exception */ @Test - public void release_published() throws Exception { - final GHEventPayload.Release event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Release.class); + public void projectsv2item_edited() throws Exception { + final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); - assertThat(event.getAction(), is("published")); - assertThat(event.getSender().getLogin(), is("seregamorph")); - assertThat(event.getRepository().getName(), is("company-rest-api-framework")); - assertThat(event.getOrganization().getLogin(), is("company-group")); - assertThat(event.getInstallation(), nullValue()); - assertThat(event.getRelease().getName(), is("4.2")); - assertThat(event.getRelease().getTagName(), is("rest-api-framework-4.2")); - assertThat(event.getRelease().getBody(), is("REST-269 - unique test executions (#86) Sergey Chernov")); + assertThat(projectsV2ItemPayload.getAction(), is("edited")); + + assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532028000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1659532033000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue())); + + assertThat(projectsV2ItemPayload.getChanges().getFieldValue().getFieldNodeId(), + is("PVTF_lADOBNft-M4AEjBWzgCnp5Q")); + assertThat(projectsV2ItemPayload.getChanges().getFieldValue().getFieldType(), is(FieldType.SINGLE_SELECT)); } /** - * Repository. + * Projectsv 2 item archived. * * @throws Exception * the exception */ @Test - public void repository() throws Exception { - final GHEventPayload.Repository event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); - assertThat(event.getAction(), is("created")); - assertThat(event.getRepository().getName(), is("new-repository")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterandthehackers")); - assertThat(event.getOrganization().getLogin(), is("baxterandthehackers")); - assertThat(event.getSender().getLogin(), is("baxterthehacker")); + public void projectsv2item_archived() throws Exception { + final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); + + assertThat(projectsV2ItemPayload.getAction(), is("archived")); + + assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083794L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532431000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1660086629000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt().getTime(), is(1660086629000L)); + + assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getFrom(), is(nullValue())); + assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getTo().getTime(), is(1660086629000L)); } /** - * Repository renamed. + * Projectsv 2 item restored. * * @throws Exception * the exception */ @Test - public void repository_renamed() throws Exception { - final GHEventPayload.Repository event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); - assertThat(event.getAction(), is("renamed")); - assertThat(event.getChanges().getRepository().getName().getFrom(), is("react-workshop")); - assertThat(event.getRepository().getName(), is("react-workshop-renamed")); - assertThat(event.getRepository().getOwner().getLogin(), is("EJG-Organization")); - assertThat(event.getOrganization().getLogin(), is("EJG-Organization")); - assertThat(event.getSender().getLogin(), is("eleanorgoh")); + public void projectsv2item_restored() throws Exception { + final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); + + assertThat(projectsV2ItemPayload.getAction(), is("restored")); + + assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083254L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532028000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1659532419000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue())); + + assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getFrom().getTime(), is(1659532142000L)); + assertThat(projectsV2ItemPayload.getChanges().getArchivedAt().getTo(), is(nullValue())); } /** - * Repository ownership transferred to an organization. + * Projectsv 2 item reordered. * * @throws Exception * the exception */ @Test - public void repository_transferred_to_org() throws Exception { - final GHEventPayload.Repository event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); - assertThat(event.getAction(), is("transferred")); - assertThat(event.getChanges().getOwner().getFrom().getUser().getLogin(), is("eleanorgoh")); - assertThat(event.getChanges().getOwner().getFrom().getUser().getId(), is(66235606L)); - assertThat(event.getChanges().getOwner().getFrom().getUser().getType(), is("User")); + public void projectsv2item_reordered() throws Exception { + final GHEventPayload.ProjectsV2Item projectsV2ItemPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.ProjectsV2Item.class); + + assertThat(projectsV2ItemPayload.getAction(), is("reordered")); + + assertThat(projectsV2ItemPayload.getProjectsV2Item().getId(), is(8083794L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getCreatedAt().getTime(), is(1659532431000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getUpdatedAt().getTime(), is(1659532439000L)); + assertThat(projectsV2ItemPayload.getProjectsV2Item().getArchivedAt(), is(nullValue())); + + assertThat(projectsV2ItemPayload.getChanges().getPreviousProjectsV2ItemNodeId().getFrom(), + is("PVTI_lADOBNft-M4AEjBWzgB7VzY")); + assertThat(projectsV2ItemPayload.getChanges().getPreviousProjectsV2ItemNodeId().getTo(), + is("PVTI_lADOBNft-M4AEjBWzgB7VzY")); } /** - * Repository ownership transferred to a user. + * Membership added. * * @throws Exception * the exception */ @Test - public void repository_transferred_to_user() throws Exception { - final GHEventPayload.Repository event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); - assertThat(event.getAction(), is("transferred")); - assertThat(event.getChanges().getOwner().getFrom().getOrganization().getLogin(), is("EJG-Organization")); - assertThat(event.getChanges().getOwner().getFrom().getOrganization().getId(), is(168135412L)); - assertThat(event.getRepository().getOwner().getLogin(), is("eleanorgoh")); - assertThat(event.getRepository().getOwner().getType(), is("User")); + public void membership_added() throws Exception { + final GHEventPayload.Membership membershipPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Membership.class); + + assertThat(membershipPayload.getAction(), is("added")); + + assertThat(membershipPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); + + GHUser member = membershipPayload.getMember(); + assertThat(member.getId(), is(1279749L)); + assertThat(member.getLogin(), is("gsmet")); + + GHTeam team = membershipPayload.getTeam(); + assertThat(team.getId(), is(9709063L)); + assertThat(team.getName(), is("New team")); + assertThat(team.getNodeId(), is("T_kwDOBNft-M4AlCYH")); + assertThat(team.getDescription(), is("Description")); + assertThat(team.getPrivacy(), is(Privacy.CLOSED)); + assertThat(team.getOrganization().getLogin(), is("gsmet-bot-playground")); } /** - * Starred. + * Member edited. * * @throws Exception * the exception */ @Test - public void starred() throws Exception { - final GHEventPayload.Star starPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Star.class); + public void member_edited() throws Exception { + final GHEventPayload.Member memberPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Member.class); - assertThat(starPayload.getAction(), is("created")); - assertThat(starPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(starPayload.getSender().getLogin(), is("gsmet")); - assertThat(starPayload.getStarredAt().toEpochMilli(), is(1654017876000L)); + assertThat(memberPayload.getAction(), is("edited")); + + assertThat(memberPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); + assertThat(memberPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-playground")); + + GHUser member = memberPayload.getMember(); + assertThat(member.getId(), is(412878L)); + assertThat(member.getLogin(), is("yrodiere")); + + GHMemberChanges changes = memberPayload.getChanges(); + assertThat(changes.getPermission().getFrom(), is("admin")); + assertThat(changes.getPermission().getTo(), is("triage")); } /** - * Status. + * Member added. * * @throws Exception * the exception */ @Test - public void status() throws Exception { - final GHEventPayload.Status event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Status.class); - assertThat(event.getContext(), is("default")); - assertThat(event.getDescription(), is("status description")); - assertThat(event.getState(), is(GHCommitState.SUCCESS)); - assertThat(event.getCommit().getSHA1(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); - assertThat(event.getTargetUrl(), nullValue()); - assertThat(event.getCommit().getOwner(), sameInstance(event.getRepository())); + public void member_added() throws Exception { + final GHEventPayload.Member memberPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Member.class); + + assertThat(memberPayload.getAction(), is("added")); + + assertThat(memberPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); + assertThat(memberPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-playground")); + + GHUser member = memberPayload.getMember(); + assertThat(member.getId(), is(412878L)); + assertThat(member.getLogin(), is("yrodiere")); + + GHMemberChanges changes = memberPayload.getChanges(); + assertThat(changes.getPermission().getFrom(), is(nullValue())); + assertThat(changes.getPermission().getTo(), is("admin")); } /** - * Status 2. + * Member added with role name defined. * * @throws Exception * the exception */ @Test - public void status2() throws Exception { - final GHEventPayload.Status event = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Status.class); - assertThat(event.getTargetUrl(), is("https://www.wikipedia.org/")); + public void member_added_role_name() throws Exception { + final GHEventPayload.Member memberPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Member.class); - assertThat(event.getCommit().getOwner(), sameInstance(event.getRepository())); + assertThat(memberPayload.getAction(), is("added")); + + assertThat(memberPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); + assertThat(memberPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-playground")); + + GHUser member = memberPayload.getMember(); + assertThat(member.getId(), is(412878L)); + assertThat(member.getLogin(), is("yrodiere")); + + GHMemberChanges changes = memberPayload.getChanges(); + assertThat(changes.getPermission().getFrom(), is(nullValue())); + assertThat(changes.getPermission().getTo(), is("write")); + assertThat(changes.getRoleName().getTo(), is("maintain")); } /** @@ -1598,60 +1849,27 @@ public void team_created() throws Exception { * the exception */ @Test - public void team_edited_description() throws Exception { - final GHEventPayload.Team teamPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.Team.class); - - assertThat(teamPayload.getAction(), is("edited")); - - assertThat(teamPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); - - GHTeam team = teamPayload.getTeam(); - assertThat(team.getId(), is(9709063L)); - assertThat(team.getName(), is("New team")); - assertThat(team.getNodeId(), is("T_kwDOBNft-M4AlCYH")); - assertThat(team.getDescription(), is("New description")); - assertThat(team.getPrivacy(), is(Privacy.CLOSED)); - assertThat(team.getOrganization().getLogin(), is("gsmet-bot-playground")); - - GHTeamChanges changes = teamPayload.getChanges(); - assertThat(changes.getDescription().getFrom(), is("Description")); - assertThat(changes.getName(), is(nullValue())); - assertThat(changes.getPrivacy(), is(nullValue())); - assertThat(changes.getRepository(), is(nullValue())); - } - - /** - * Team edited repository permission. - * - * @throws Exception - * the exception - */ - @Test - public void team_edited_permission() throws Exception { + public void team_edited_description() throws Exception { final GHEventPayload.Team teamPayload = GitHub.offline() .parseEventPayload(payload.asReader(), GHEventPayload.Team.class); assertThat(teamPayload.getAction(), is("edited")); assertThat(teamPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); - assertThat(teamPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-app")); GHTeam team = teamPayload.getTeam(); assertThat(team.getId(), is(9709063L)); assertThat(team.getName(), is("New team")); assertThat(team.getNodeId(), is("T_kwDOBNft-M4AlCYH")); assertThat(team.getDescription(), is("New description")); - assertThat(team.getPrivacy(), is(Privacy.SECRET)); + assertThat(team.getPrivacy(), is(Privacy.CLOSED)); assertThat(team.getOrganization().getLogin(), is("gsmet-bot-playground")); GHTeamChanges changes = teamPayload.getChanges(); - assertThat(changes.getDescription(), is(nullValue())); + assertThat(changes.getDescription().getFrom(), is("Description")); assertThat(changes.getName(), is(nullValue())); assertThat(changes.getPrivacy(), is(nullValue())); - assertThat(changes.getRepository().getPermissions().hadPushAccess(), is(false)); - assertThat(changes.getRepository().getPermissions().hadPullAccess(), is(true)); - assertThat(changes.getRepository().getPermissions().hadAdminAccess(), is(false)); + assertThat(changes.getRepository(), is(nullValue())); } /** @@ -1685,247 +1903,35 @@ public void team_edited_visibility() throws Exception { } /** - * Workflow dispatch. - * - * @throws Exception - * the exception - */ - @Test - public void workflow_dispatch() throws Exception { - final GHEventPayload.WorkflowDispatch workflowDispatchPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowDispatch.class); - - assertThat(workflowDispatchPayload.getRef(), is("refs/heads/main")); - assertThat(workflowDispatchPayload.getAction(), is(nullValue())); - assertThat(workflowDispatchPayload.getWorkflow(), is(".github/workflows/main.yml")); - assertThat(workflowDispatchPayload.getInputs(), aMapWithSize(1)); - assertThat(workflowDispatchPayload.getInputs().keySet(), contains("logLevel")); - assertThat(workflowDispatchPayload.getInputs().values(), contains("warning")); - assertThat(workflowDispatchPayload.getRepository().getName(), is("quarkus-bot-java-playground")); - assertThat(workflowDispatchPayload.getSender().getLogin(), is("gsmet")); - } - - /** - * Workflow job. - * - * @throws Exception - * the exception - */ - @Test - public void workflow_job() throws Exception { - final GHEventPayload.WorkflowJob workflowJobPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowJob.class); - - assertThat(workflowJobPayload.getAction(), is("completed")); - assertThat(workflowJobPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(workflowJobPayload.getSender().getLogin(), is("gsmet")); - - GHWorkflowJob workflowJob = workflowJobPayload.getWorkflowJob(); - assertThat(workflowJob.getId(), is(6653410527L)); - assertThat(workflowJob.getRunId(), is(2408553341L)); - assertThat(workflowJob.getRunAttempt(), is(1)); - assertThat(workflowJob.getUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/jobs/6653410527")); - assertThat(workflowJob.getHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/runs/6653410527?check_suite_focus=true")); - assertThat(workflowJob.getNodeId(), is("CR_kwDOEq3cwc8AAAABjJL83w")); - assertThat(workflowJob.getHeadSha(), is("5dd2dadfbdc2a722c08a8ad42ae4e26e3e731042")); - assertThat(workflowJob.getStatus(), is(GHWorkflowRun.Status.COMPLETED)); - assertThat(workflowJob.getConclusion(), is(GHWorkflowRun.Conclusion.FAILURE)); - assertThat(workflowJob.getStartedAt().toEpochMilli(), is(1653908125000L)); - assertThat(workflowJob.getCompletedAt().toEpochMilli(), is(1653908157000L)); - assertThat(workflowJob.getName(), is("JVM Tests - JDK JDK16")); - assertThat(workflowJob.getSteps(), - contains(hasProperty("name", is("Set up job")), - hasProperty("name", is("Run actions/checkout@v2")), - hasProperty("name", is("Build with Maven")), - hasProperty("name", is("Post Run actions/checkout@v2")), - hasProperty("name", is("Complete job")))); - assertThat(workflowJob.getCheckRunUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/check-runs/6653410527")); - } - - /** - * Workflow run. - * - * @throws Exception - * the exception - */ - @Test - public void workflow_run() throws Exception { - final GHEventPayload.WorkflowRun workflowRunPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowRun.class); - - assertThat(workflowRunPayload.getAction(), is("completed")); - assertThat(workflowRunPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(workflowRunPayload.getSender().getLogin(), is("gsmet")); - - GHWorkflow workflow = workflowRunPayload.getWorkflow(); - assertThat(workflow.getId(), is(7087581L)); - assertThat(workflow.getName(), is("CI")); - assertThat(workflow.getPath(), is(".github/workflows/main.yml")); - assertThat(workflow.getState(), is("active")); - assertThat(workflow.getUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/workflows/7087581")); - assertThat(workflow.getHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/blob/main/.github/workflows/main.yml")); - assertThat(workflow.getBadgeUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/workflows/CI/badge.svg")); - - GHWorkflowRun workflowRun = workflowRunPayload.getWorkflowRun(); - assertThat(workflowRun.getId(), is(680604745L)); - assertThat(workflowRun.getName(), is("CI")); - assertThat(workflowRun.getHeadBranch(), is("main")); - assertThat(workflowRun.getDisplayTitle(), is("its-display-title")); - assertThat(workflowRun.getHeadSha(), is("dbea8d8b6ed2cf764dfd84a215f3f9040b3d4423")); - assertThat(workflowRun.getRunNumber(), is(6L)); - assertThat(workflowRun.getEvent(), is(GHEvent.WORKFLOW_DISPATCH)); - assertThat(workflowRun.getStatus(), is(GHWorkflowRun.Status.COMPLETED)); - assertThat(workflowRun.getConclusion(), is(GHWorkflowRun.Conclusion.SUCCESS)); - assertThat(workflowRun.getWorkflowId(), is(7087581L)); - assertThat(workflowRun.getUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745")); - assertThat(workflowRun.getHtmlUrl().toString(), - is("https://github.com/gsmet/quarkus-bot-java-playground/actions/runs/680604745")); - assertThat(workflowRun.getJobsUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/jobs")); - assertThat(workflowRun.getLogsUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/logs")); - assertThat(workflowRun.getCheckSuiteUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/check-suites/2327154397")); - assertThat(workflowRun.getArtifactsUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/artifacts")); - assertThat(workflowRun.getCancelUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/cancel")); - assertThat(workflowRun.getRerunUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/runs/680604745/rerun")); - assertThat(workflowRun.getWorkflowUrl().toString(), - is("https://api.github.com/repos/gsmet/quarkus-bot-java-playground/actions/workflows/7087581")); - assertThat(workflowRun.getCreatedAt().toEpochMilli(), is(1616524526000L)); - assertThat(workflowRun.getUpdatedAt().toEpochMilli(), is(1616524543000L)); - assertThat(workflowRun.getRunAttempt(), is(1L)); - assertThat(workflowRun.getRunStartedAt().toEpochMilli(), is(1616524526000L)); - assertThat(workflowRun.getHeadCommit().getId(), is("dbea8d8b6ed2cf764dfd84a215f3f9040b3d4423")); - assertThat(workflowRun.getHeadCommit().getTreeId(), is("b17089e6a2574ec1002566fe980923e62dce3026")); - assertThat(workflowRun.getHeadCommit().getMessage(), is("Update main.yml")); - assertThat(workflowRun.getHeadCommit().getTimestamp().toEpochMilli(), is(1616523390000L)); - assertThat(workflowRun.getHeadCommit().getAuthor().getName(), is("Guillaume Smet")); - assertThat(workflowRun.getHeadCommit().getAuthor().getEmail(), is("guillaume.smet@gmail.com")); - assertThat(workflowRun.getHeadCommit().getCommitter().getName(), is("GitHub")); - assertThat(workflowRun.getHeadCommit().getCommitter().getEmail(), is("noreply@github.com")); - assertThat(workflowRun.getHeadRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(workflowRun.getRepository(), sameInstance(workflowRunPayload.getRepository())); - } - - /** - * Workflow run other repository. - * - * @throws Exception - * the exception - */ - @Test - public void workflow_run_other_repository() throws Exception { - final GHEventPayload.WorkflowRun workflowRunPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowRun.class); - GHWorkflowRun workflowRun = workflowRunPayload.getWorkflowRun(); - - assertThat(workflowRunPayload.getRepository().getFullName(), is("gsmet/quarkus-bot-java-playground")); - assertThat(workflowRun.getHeadRepository().getFullName(), - is("gsmet-bot-playground/quarkus-bot-java-playground")); - assertThat(workflowRun.getRepository(), sameInstance(workflowRunPayload.getRepository())); - assertThat(workflowRunPayload.getWorkflow().getRepository(), sameInstance(workflowRunPayload.getRepository())); - } - - /** - * Workflow run pull request. + * Team edited repository permission. * * @throws Exception * the exception */ @Test - public void workflow_run_pull_request() throws Exception { - final GHEventPayload.WorkflowRun workflowRunPayload = GitHub.offline() - .parseEventPayload(payload.asReader(), GHEventPayload.WorkflowRun.class); - - List pullRequests = workflowRunPayload.getWorkflowRun().getPullRequests(); - assertThat(pullRequests.size(), is(1)); - - GHPullRequest pullRequest = pullRequests.get(0); - assertThat(pullRequest.getId(), is(599098265L)); - assertThat(pullRequest.getRepository(), sameInstance(workflowRunPayload.getRepository())); - } - - private GHCheckRun verifyBasicCheckRunEvent(final GHEventPayload.CheckRun event) throws IOException { - assertThat(event.getRepository().getName(), is("Hello-World")); - assertThat(event.getRepository().getOwner().getLogin(), is("Codertocat")); - assertThat(event.getAction(), is("created")); - assertThat(event.getRequestedAction(), nullValue()); - - // Checks the deserialization of check_run - final GHCheckRun checkRun = event.getCheckRun(); - assertThat(checkRun.getName(), is("Octocoders-linter")); - assertThat(checkRun.getHeadSha(), is("ec26c3e57ca3a959ca5aad62de7213c562f8c821")); - assertThat(checkRun.getStatus(), is(Status.COMPLETED)); - assertThat(checkRun.getNodeId(), is("MDg6Q2hlY2tSdW4xMjg2MjAyMjg=")); - assertThat(checkRun.getExternalId(), is("")); - - assertThat(GitHubClient.printInstant(checkRun.getStartedAt()), is("2019-05-15T15:21:12Z")); - assertThat(GitHubClient.printInstant(checkRun.getCompletedAt()), is("2019-05-15T20:22:22Z")); - - assertThat(checkRun.getConclusion(), is(Conclusion.SUCCESS)); - assertThat(checkRun.getUrl().toString(), endsWith("/repos/Codertocat/Hello-World/check-runs/128620228")); - assertThat(checkRun.getHtmlUrl().toString(), - endsWith("https://github.com/Codertocat/Hello-World/runs/128620228")); - assertThat(checkRun.getDetailsUrl().toString(), is("https://octocoders.io")); - assertThat(checkRun.getApp().getId(), is(29310L)); - assertThat(checkRun.getCheckSuite().getId(), is(118578147L)); - assertThat(checkRun.getOutput().getTitle(), is("check-run output")); - assertThat(checkRun.getOutput().getSummary(), nullValue()); - assertThat(checkRun.getOutput().getText(), nullValue()); - assertThat(checkRun.getOutput().getAnnotationsCount(), is(0)); - assertThat(checkRun.getOutput().getAnnotationsUrl().toString(), - endsWith("/repos/Codertocat/Hello-World/check-runs/128620228/annotations")); - - // Checks the deserialization of sender - assertThat(event.getSender().getId(), is(21031067L)); - - assertThat(checkRun.getPullRequests(), notNullValue()); - assertThat(checkRun.getPullRequests().size(), equalTo(1)); - assertThat(checkRun.getPullRequests().get(0).getNumber(), equalTo(2)); - return checkRun; - } - - private GHCheckSuite verifyBasicCheckSuiteEvent(final GHEventPayload.CheckSuite event) throws IOException { - assertThat(event.getRepository().getName(), is("Hello-World")); - assertThat(event.getRepository().getOwner().getLogin(), is("Codertocat")); - assertThat(event.getAction(), is("completed")); - assertThat(event.getSender().getId(), is(21031067L)); + public void team_edited_permission() throws Exception { + final GHEventPayload.Team teamPayload = GitHub.offline() + .parseEventPayload(payload.asReader(), GHEventPayload.Team.class); - // Checks the deserialization of check_suite - final GHCheckSuite checkSuite = event.getCheckSuite(); - assertThat(checkSuite.getNodeId(), is("MDEwOkNoZWNrU3VpdGUxMTg1NzgxNDc=")); - assertThat(checkSuite.getHeadBranch(), is("changes")); - assertThat(checkSuite.getHeadSha(), is("ec26c3e57ca3a959ca5aad62de7213c562f8c821")); - assertThat(checkSuite.getStatus(), is("completed")); - assertThat(checkSuite.getConclusion(), is("success")); - assertThat(checkSuite.getBefore(), is("6113728f27ae82c7b1a177c8d03f9e96e0adf246")); - assertThat(checkSuite.getAfter(), is("ec26c3e57ca3a959ca5aad62de7213c562f8c821")); - assertThat(checkSuite.getLatestCheckRunsCount(), is(1)); - assertThat(checkSuite.getCheckRunsUrl().toString(), - endsWith("/repos/Codertocat/Hello-World/check-suites/118578147/check-runs")); - assertThat(checkSuite.getHeadCommit().getMessage(), is("Update README.md")); - assertThat(checkSuite.getHeadCommit().getId(), is("ec26c3e57ca3a959ca5aad62de7213c562f8c821")); - assertThat(checkSuite.getHeadCommit().getTreeId(), is("31b122c26a97cf9af023e9ddab94a82c6e77b0ea")); - assertThat(checkSuite.getHeadCommit().getAuthor().getName(), is("Codertocat")); - assertThat(checkSuite.getHeadCommit().getCommitter().getName(), is("Codertocat")); + assertThat(teamPayload.getAction(), is("edited")); - assertThat(GitHubClient.printInstant(checkSuite.getHeadCommit().getTimestamp()), is("2019-05-15T15:20:30Z")); + assertThat(teamPayload.getOrganization().getLogin(), is("gsmet-bot-playground")); + assertThat(teamPayload.getRepository().getName(), is("github-automation-with-quarkus-demo-app")); - assertThat(checkSuite.getApp().getId(), is(29310L)); + GHTeam team = teamPayload.getTeam(); + assertThat(team.getId(), is(9709063L)); + assertThat(team.getName(), is("New team")); + assertThat(team.getNodeId(), is("T_kwDOBNft-M4AlCYH")); + assertThat(team.getDescription(), is("New description")); + assertThat(team.getPrivacy(), is(Privacy.SECRET)); + assertThat(team.getOrganization().getLogin(), is("gsmet-bot-playground")); - assertThat(checkSuite.getPullRequests(), notNullValue()); - assertThat(checkSuite.getPullRequests().size(), equalTo(1)); - assertThat(checkSuite.getPullRequests().get(0).getNumber(), equalTo(2)); - return checkSuite; + GHTeamChanges changes = teamPayload.getChanges(); + assertThat(changes.getDescription(), is(nullValue())); + assertThat(changes.getName(), is(nullValue())); + assertThat(changes.getPrivacy(), is(nullValue())); + assertThat(changes.getRepository().getPermissions().hadPushAccess(), is(false)); + assertThat(changes.getRepository().getPermissions().hadPullAccess(), is(true)); + assertThat(changes.getRepository().getPermissions().hadAdminAccess(), is(false)); } } diff --git a/src/test/java/org/kohsuke/github/GHEventTest.java b/src/test/java/org/kohsuke/github/GHEventTest.java index 5c6f8225ee..900063d2b8 100644 --- a/src/test/java/org/kohsuke/github/GHEventTest.java +++ b/src/test/java/org/kohsuke/github/GHEventTest.java @@ -11,6 +11,12 @@ */ public class GHEventTest { + /** + * Create default GHEventTest instance + */ + public GHEventTest() { + } + /** * Function from GHEventInfo to transform string event to GHEvent which has been replaced by static mapping due to * complex parsing logic below @@ -27,12 +33,6 @@ private static GHEvent oldTransformationFunction(String t) { return GHEvent.UNKNOWN; } - /** - * Create default GHEventTest instance - */ - public GHEventTest() { - } - /** * Regression test. */ diff --git a/src/test/java/org/kohsuke/github/GHExternalGroupTest.java b/src/test/java/org/kohsuke/github/GHExternalGroupTest.java index bd6e33156e..da0696eece 100644 --- a/src/test/java/org/kohsuke/github/GHExternalGroupTest.java +++ b/src/test/java/org/kohsuke/github/GHExternalGroupTest.java @@ -23,13 +23,13 @@ public GHExternalGroupTest() { } /** - * Test get organization. + * Test refresh bound external group. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetOrganization() throws IOException { + public void testRefreshBoundExternalGroup() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); List groups = org.listExternalGroups().toList(); @@ -37,19 +37,29 @@ public void testGetOrganization() throws IOException { assertThat(sut, isExternalGroupSummary()); - final GHOrganization other = sut.getOrganization(); + sut.refresh(); - assertThat(other, is(org)); + assertThat(sut.getId(), equalTo(467431L)); + assertThat(sut.getName(), equalTo("acme-developers")); + assertThat(sut.getUpdatedAt(), notNullValue()); + + assertThat(sut.getMembers(), notNullValue()); + assertThat(membersSummary(sut), + hasItems("158311279:john-doe_acme:John Doe:john.doe@acme.corp", + "166731041:jane-doe_acme:Jane Doe:jane.doe@acme.corp")); + + assertThat(sut.getTeams(), notNullValue()); + assertThat(teamSummary(sut), hasItems("9891173:ACME-DEVELOPERS")); } /** - * Test refresh bound external group. + * Test get organization. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testRefreshBoundExternalGroup() throws IOException { + public void testGetOrganization() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); List groups = org.listExternalGroups().toList(); @@ -57,19 +67,9 @@ public void testRefreshBoundExternalGroup() throws IOException { assertThat(sut, isExternalGroupSummary()); - sut.refresh(); - - assertThat(sut.getId(), equalTo(467431L)); - assertThat(sut.getName(), equalTo("acme-developers")); - assertThat(sut.getUpdatedAt(), notNullValue()); - - assertThat(sut.getMembers(), notNullValue()); - assertThat(membersSummary(sut), - hasItems("158311279:john-doe_acme:John Doe:john.doe@acme.corp", - "166731041:jane-doe_acme:Jane Doe:jane.doe@acme.corp")); + final GHOrganization other = sut.getOrganization(); - assertThat(sut.getTeams(), notNullValue()); - assertThat(teamSummary(sut), hasItems("9891173:ACME-DEVELOPERS")); + assertThat(other, is(org)); } } diff --git a/src/test/java/org/kohsuke/github/GHGistTest.java b/src/test/java/org/kohsuke/github/GHGistTest.java index 76a02871b4..14e02f1c23 100644 --- a/src/test/java/org/kohsuke/github/GHGistTest.java +++ b/src/test/java/org/kohsuke/github/GHGistTest.java @@ -20,33 +20,6 @@ public class GHGistTest extends AbstractGitHubWireMockTest { public GHGistTest() { } - /** - * Gist file. - * - * @throws Exception - * the exception - */ - @Test - public void gistFile() throws Exception { - GHGist gist = gitHub.getGist("9903708"); - - assertThat(gist.isPublic(), is(true)); - assertThat(gist.getId(), equalTo(9903708L)); - assertThat(gist.getGistId(), equalTo("9903708")); - - assertThat(gist.getFiles().size(), equalTo(1)); - GHGistFile f = gist.getFile("keybase.md"); - - assertThat(f.getType(), equalTo("text/markdown")); - assertThat(f.getLanguage(), equalTo("Markdown")); - assertThat(f.getContent(), containsString("### Keybase proof")); - assertThat(f.getRawUrl().toString(), - equalTo("https://gist.githubusercontent.com/rtyler/9903708/raw/2b68396d836af8c5b6ba905f27c4baf94ceb0ed3/keybase.md")); - assertThat(f.getFileName(), equalTo("keybase.md")); - assertThat(f.getSize(), equalTo(2131)); - assertThat(f.isTruncated(), equalTo(false)); - } - /** * Lifecycle test. * @@ -174,4 +147,26 @@ public void starTest() throws Exception { newGist.delete(); } } + + /** + * Gist file. + * + * @throws Exception + * the exception + */ + @Test + public void gistFile() throws Exception { + GHGist gist = gitHub.getGist("9903708"); + + assertThat(gist.isPublic(), is(true)); + assertThat(gist.getId(), equalTo(9903708L)); + assertThat(gist.getGistId(), equalTo("9903708")); + + assertThat(gist.getFiles().size(), equalTo(1)); + GHGistFile f = gist.getFile("keybase.md"); + + assertThat(f.getType(), equalTo("text/markdown")); + assertThat(f.getLanguage(), equalTo("Markdown")); + assertThat(f.getContent(), containsString("### Keybase proof")); + } } diff --git a/src/test/java/org/kohsuke/github/GHGistUpdaterTest.java b/src/test/java/org/kohsuke/github/GHGistUpdaterTest.java index 24db84ac63..e5626fc034 100644 --- a/src/test/java/org/kohsuke/github/GHGistUpdaterTest.java +++ b/src/test/java/org/kohsuke/github/GHGistUpdaterTest.java @@ -17,29 +17,13 @@ */ public class GHGistUpdaterTest extends AbstractGitHubWireMockTest { - private GHGist gist; - /** * Create default GHGistUpdaterTest instance */ public GHGistUpdaterTest() { } - /** - * Clean up. - * - * @throws Exception - * the exception - */ - @After - public void cleanUp() throws Exception { - // Cleanup is only needed when proxying - if (!mockGitHub.isUseProxy()) { - return; - } - - gist.delete(); - } + private GHGist gist; /** * Sets the up. @@ -59,6 +43,22 @@ public void setUp() throws IOException { .create(); } + /** + * Clean up. + * + * @throws Exception + * the exception + */ + @After + public void cleanUp() throws Exception { + // Cleanup is only needed when proxying + if (!mockGitHub.isUseProxy()) { + return; + } + + gist.delete(); + } + /** * Test git updater. * diff --git a/src/test/java/org/kohsuke/github/GHIssueEventAttributeTest.java b/src/test/java/org/kohsuke/github/GHIssueEventAttributeTest.java index 152e377311..73d04232d6 100644 --- a/src/test/java/org/kohsuke/github/GHIssueEventAttributeTest.java +++ b/src/test/java/org/kohsuke/github/GHIssueEventAttributeTest.java @@ -21,10 +21,16 @@ */ public class GHIssueEventAttributeTest extends AbstractGitHubWireMockTest { + /** + * Create default GHIssueEventAttributeTest instance + */ + public GHIssueEventAttributeTest() { + } + private enum Type implements Predicate, Consumer { - assignment(e -> assertThat(e.getAssignee(), notNullValue()), "assigned", "unassigned"), + milestone(e -> assertThat(e.getMilestone(), notNullValue()), "milestoned", "demilestoned"), label(e -> assertThat(e.getLabel(), notNullValue()), "labeled", "unlabeled"), - milestone(e -> assertThat(e.getMilestone(), notNullValue()), "milestoned", "demilestoned"); + assignment(e -> assertThat(e.getAssignee(), notNullValue()), "assigned", "unassigned"); private final Consumer assertion; private final Set subtypes; @@ -35,20 +41,22 @@ private enum Type implements Predicate, Consumer { } @Override - public void accept(final GHIssueEvent event) { - this.assertion.accept(event); + public boolean test(final GHIssueEvent event) { + return this.subtypes.contains(event.getEvent()); } @Override - public boolean test(final GHIssueEvent event) { - return this.subtypes.contains(event.getEvent()); + public void accept(final GHIssueEvent event) { + this.assertion.accept(event); } } - /** - * Create default GHIssueEventAttributeTest instance - */ - public GHIssueEventAttributeTest() { + private List listEvents(final Type type) throws IOException { + return StreamSupport + .stream(gitHub.getRepository("chids/project-milestone-test").getIssue(1).listEvents().spliterator(), + false) + .filter(type) + .collect(toList()); } /** @@ -65,12 +73,4 @@ public void testEventSpecificAttributes() throws IOException { events.forEach(type); } } - - private List listEvents(final Type type) throws IOException { - return StreamSupport - .stream(gitHub.getRepository("chids/project-milestone-test").getIssue(1).listEvents().spliterator(), - false) - .filter(type) - .collect(toList()); - } } diff --git a/src/test/java/org/kohsuke/github/GHIssueEventTest.java b/src/test/java/org/kohsuke/github/GHIssueEventTest.java index 1404f7fde6..5ac4c2b1df 100644 --- a/src/test/java/org/kohsuke/github/GHIssueEventTest.java +++ b/src/test/java/org/kohsuke/github/GHIssueEventTest.java @@ -22,46 +22,6 @@ public class GHIssueEventTest extends AbstractGitHubWireMockTest { public GHIssueEventTest() { } - /** - * Test events for issue rename. - * - * @throws Exception - * the exception - */ - @Test - public void testEventsForIssueRename() throws Exception { - // Create the issue. - GHRepository repo = getRepository(); - GHIssueBuilder builder = repo.createIssue("Some invalid issue name"); - GHIssue issue = builder.create(); - - // Generate rename event. - issue.setTitle("Fixed issue name"); - - // Test that the event is present. - List list = issue.listEvents().toList(); - assertThat(list.size(), equalTo(1)); - - GHIssueEvent event = list.get(0); - assertThat(event.getIssue().getNumber(), equalTo(issue.getNumber())); - assertThat(event.getEvent(), equalTo("renamed")); - assertThat(event.getRename(), notNullValue()); - assertThat(event.getRename().getFrom(), equalTo("Some invalid issue name")); - assertThat(event.getRename().getTo(), equalTo("Fixed issue name")); - - // Test that we can get a single event directly. - GHIssueEvent eventFromRepo = repo.getIssueEvent(event.getId()); - assertThat(eventFromRepo.getId(), equalTo(event.getId())); - assertThat(eventFromRepo.getCreatedAt(), equalTo(event.getCreatedAt())); - assertThat(eventFromRepo.getEvent(), equalTo("renamed")); - assertThat(eventFromRepo.getRename(), notNullValue()); - assertThat(eventFromRepo.getRename().getFrom(), equalTo("Some invalid issue name")); - assertThat(eventFromRepo.getRename().getTo(), equalTo("Fixed issue name")); - - // Close the issue. - issue.close(); - } - /** * Test events for single issue. * @@ -121,15 +81,51 @@ public void testIssueReviewRequestedEvent() throws Exception { assertThat(event.getReviewRequester().getLogin(), equalTo("t0m4uk1991")); assertThat(event.getRequestedReviewer(), notNullValue()); assertThat(event.getRequestedReviewer().getLogin(), equalTo("bitwiseman")); - assertThat(event.getNodeId(), equalTo("MDIwOlJldmlld1JlcXVlc3RlZEV2ZW50NTA2NDM2MzE3OQ==")); - assertThat(event.getCommitId(), nullValue()); - assertThat(event.getCommitUrl(), nullValue()); - assertThat(event.toString(), equalTo("Issue 434 was review_requested by t0m4uk1991 on 2021-07-24T20:28:28Z")); // Close the PR. pullRequest.close(); } + /** + * Test events for issue rename. + * + * @throws Exception + * the exception + */ + @Test + public void testEventsForIssueRename() throws Exception { + // Create the issue. + GHRepository repo = getRepository(); + GHIssueBuilder builder = repo.createIssue("Some invalid issue name"); + GHIssue issue = builder.create(); + + // Generate rename event. + issue.setTitle("Fixed issue name"); + + // Test that the event is present. + List list = issue.listEvents().toList(); + assertThat(list.size(), equalTo(1)); + + GHIssueEvent event = list.get(0); + assertThat(event.getIssue().getNumber(), equalTo(issue.getNumber())); + assertThat(event.getEvent(), equalTo("renamed")); + assertThat(event.getRename(), notNullValue()); + assertThat(event.getRename().getFrom(), equalTo("Some invalid issue name")); + assertThat(event.getRename().getTo(), equalTo("Fixed issue name")); + + // Test that we can get a single event directly. + GHIssueEvent eventFromRepo = repo.getIssueEvent(event.getId()); + assertThat(eventFromRepo.getId(), equalTo(event.getId())); + assertThat(eventFromRepo.getCreatedAt(), equalTo(event.getCreatedAt())); + assertThat(eventFromRepo.getEvent(), equalTo("renamed")); + assertThat(eventFromRepo.getRename(), notNullValue()); + assertThat(eventFromRepo.getRename().getFrom(), equalTo("Some invalid issue name")); + assertThat(eventFromRepo.getRename().getTo(), equalTo("Fixed issue name")); + + // Close the issue. + issue.close(); + } + /** * Test repository events. * @@ -143,26 +139,11 @@ public void testRepositoryEvents() throws Exception { assertThat(list, is(not(empty()))); int i = 0; - int successfulChecks = 0; for (GHIssueEvent event : list) { - - if ("merged".equals(event.getEvent()) - && "ecec449372b1e8270524a35c1a5aa8fdaf0e6676".equals(event.getCommitId())) { - assertThat(event.getCommitUrl(), endsWith("/ecec449372b1e8270524a35c1a5aa8fdaf0e6676")); - assertThat(event.getActor().getLogin(), equalTo("bitwiseman")); - assertThat(event.getActor().getLogin(), equalTo("bitwiseman")); - assertThat(event.getIssue().getPullRequest().getUrl().toString(), endsWith("/github-api/pull/267")); - successfulChecks++; - } assertThat(event.getIssue(), notNullValue()); - if (i++ > 100) + if (i++ > 10) break; } - assertThat("All issue checks must be found and passed", successfulChecks, equalTo(1)); - } - - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); } /** @@ -175,4 +156,8 @@ private GHRepository getRepository(GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } } diff --git a/src/test/java/org/kohsuke/github/GHIssueTest.java b/src/test/java/org/kohsuke/github/GHIssueTest.java index 6fdaf379bc..57dd7e5917 100644 --- a/src/test/java/org/kohsuke/github/GHIssueTest.java +++ b/src/test/java/org/kohsuke/github/GHIssueTest.java @@ -3,9 +3,10 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Disabled; import java.io.IOException; -import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.Collection; import java.util.Date; import java.util.List; @@ -35,67 +36,6 @@ public class GHIssueTest extends AbstractGitHubWireMockTest { public GHIssueTest() { } - /** - * Adds the labels. - * - * @throws Exception - * the exception - */ - @Test - // Requires push access to the test repo to pass - public void addLabels() throws Exception { - GHIssue issue = getRepository().createIssue("addLabels").body("## test").create(); - String addedLabel1 = "addLabels_label_name_1"; - String addedLabel2 = "addLabels_label_name_2"; - String addedLabel3 = "addLabels_label_name_3"; - - List resultingLabels = issue.addLabels(addedLabel1); - assertThat(resultingLabels.size(), equalTo(1)); - GHLabel ghLabel = resultingLabels.get(0); - assertThat(ghLabel.getName(), equalTo(addedLabel1)); - - int requestCount = mockGitHub.getRequestCount(); - resultingLabels = issue.addLabels(addedLabel2, addedLabel3); - // multiple labels can be added with one api call - assertThat(mockGitHub.getRequestCount(), equalTo(requestCount + 1)); - - assertThat(resultingLabels.size(), equalTo(3)); - assertThat(resultingLabels, - containsInAnyOrder(hasProperty("name", equalTo(addedLabel1)), - hasProperty("name", equalTo(addedLabel2)), - hasProperty("name", equalTo(addedLabel3)))); - - // Adding a label which is already present does not throw an error - resultingLabels = issue.addLabels(ghLabel); - assertThat(resultingLabels.size(), equalTo(3)); - } - - /** - * Adds the labels concurrency issue. - * - * @throws Exception - * the exception - */ - @Test - // Requires push access to the test repo to pass - public void addLabelsConcurrencyIssue() throws Exception { - String addedLabel1 = "addLabelsConcurrencyIssue_label_name_1"; - String addedLabel2 = "addLabelsConcurrencyIssue_label_name_2"; - - GHIssue issue1 = getRepository().createIssue("addLabelsConcurrencyIssue").body("## test").create(); - issue1.getLabels(); - - GHIssue issue2 = getRepository().getIssue(issue1.getNumber()); - issue2.addLabels(addedLabel2); - - Collection labels = issue1.addLabels(addedLabel1); - - assertThat(labels.size(), equalTo(2)); - assertThat(labels, - containsInAnyOrder(hasProperty("name", equalTo(addedLabel1)), - hasProperty("name", equalTo(addedLabel2)))); - } - /** * Clean up. * @@ -115,48 +55,6 @@ public void cleanUp() throws Exception { } } - /** - * Close issue. - * - * @throws Exception - * the exception - */ - @Test - public void closeIssue() throws Exception { - String name = "closeIssue"; - GHIssue issue = getRepository().createIssue(name).body("## test").create(); - assertThat(issue.getTitle(), equalTo(name)); - assertThat(getRepository().getIssue(issue.getNumber()).getState(), equalTo(GHIssueState.OPEN)); - issue.close(); - GHIssue closedIssued = getRepository().getIssue(issue.getNumber()); - assertThat(closedIssued.getState(), equalTo(GHIssueState.CLOSED)); - assertThat(closedIssued.getStateReason(), equalTo(GHIssueStateReason.COMPLETED)); - } - - /** - * Close issue as not planned. - * - * @throws Exception - * the exception - */ - @Test - public void closeIssueNotPlanned() throws Exception { - String name = "closeIssueNotPlanned"; - GHIssue issue = getRepository().createIssue(name).body("## test").create(); - assertThat(issue.getTitle(), equalTo(name)); - - GHIssue createdIssue = issue.getRepository().getIssue(issue.getNumber()); - - assertThat(createdIssue.getState(), equalTo(GHIssueState.OPEN)); - assertThat(createdIssue.getStateReason(), nullValue()); - - issue.close(GHIssueStateReason.NOT_PLANNED); - - GHIssue closedIssued = getRepository().getIssue(issue.getNumber()); - assertThat(closedIssued.getState(), equalTo(GHIssueState.CLOSED)); - assertThat(closedIssued.getStateReason(), equalTo(GHIssueStateReason.NOT_PLANNED)); - } - /** * Creates the issue. * @@ -171,24 +69,6 @@ public void createIssue() throws Exception { assertThat(issue.getTitle(), equalTo(name)); } - /** - * Gets the user test. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void getUserTest() throws IOException { - GHIssue issue = getRepository().createIssue("getUserTest").create(); - GHIssue issueSingle = getRepository().getIssue(issue.getNumber()); - assertThat(issueSingle.getUser().root(), notNullValue()); - - PagedIterable ghIssues = getRepository().queryIssues().state(GHIssueState.OPEN).list(); - for (GHIssue otherIssue : ghIssues) { - assertThat(otherIssue.getUser().root(), notNullValue()); - } - } - /** * Issue comment. * @@ -207,13 +87,13 @@ public void issueComment() throws Exception { assertThat(comments, hasSize(0)); GHIssueComment firstComment = issue.comment("First comment"); - Instant firstCommentCreatedAt = firstComment.getCreatedAt(); - Instant firstCommentCreatedAtPlus1Second = firstComment.getCreatedAt().plusSeconds(1); + Date firstCommentCreatedAt = firstComment.getCreatedAt(); + Date firstCommentCreatedAtPlus1Second = Date + .from(firstComment.getCreatedAt().toInstant().plus(1, ChronoUnit.SECONDS)); comments = issue.listComments().toList(); assertThat(comments, hasSize(1)); assertThat(comments, contains(hasProperty("body", equalTo("First comment")))); - assertThat(comments.get(0).getAuthorAssociation(), equalTo(GHCommentAuthorAssociation.NONE)); comments = issue.queryComments().list().toList(); assertThat(comments, hasSize(1)); @@ -233,12 +113,13 @@ public void issueComment() throws Exception { Thread.sleep(2000); GHIssueComment secondComment = issue.comment("Second comment"); - Instant secondCommentCreatedAt = secondComment.getCreatedAt(); - Instant secondCommentCreatedAtPlus1Second = secondComment.getCreatedAt().plusSeconds(1); + Date secondCommentCreatedAt = secondComment.getCreatedAt(); + Date secondCommentCreatedAtPlus1Second = Date + .from(secondComment.getCreatedAt().toInstant().plus(1, ChronoUnit.SECONDS)); assertThat( "There's an error in the setup of this test; please fix it." + " The second comment should be created at least one second after the first one.", - firstCommentCreatedAtPlus1Second.isBefore(secondCommentCreatedAt)); + firstCommentCreatedAtPlus1Second.getTime() <= secondCommentCreatedAt.getTime()); comments = issue.listComments().toList(); assertThat(comments, hasSize(2)); @@ -260,18 +141,144 @@ public void issueComment() throws Exception { comments = issue.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList(); assertThat(comments, hasSize(1)); assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); - comments = issue.queryComments().since(Date.from(secondCommentCreatedAt)).list().toList(); + comments = issue.queryComments().since(secondCommentCreatedAt).list().toList(); assertThat(comments, hasSize(1)); assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); comments = issue.queryComments().since(secondCommentCreatedAtPlus1Second).list().toList(); assertThat(comments, hasSize(0)); // Test "since" with timestamp instead of Date - comments = issue.queryComments().since(secondCommentCreatedAt.toEpochMilli()).list().toList(); + comments = issue.queryComments().since(secondCommentCreatedAt.getTime()).list().toList(); assertThat(comments, hasSize(1)); assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); } + /** + * Close issue. + * + * @throws Exception + * the exception + */ + @Test + public void closeIssue() throws Exception { + String name = "closeIssue"; + GHIssue issue = getRepository().createIssue(name).body("## test").create(); + assertThat(issue.getTitle(), equalTo(name)); + assertThat(getRepository().getIssue(issue.getNumber()).getState(), equalTo(GHIssueState.OPEN)); + issue.close(); + GHIssue closedIssued = getRepository().getIssue(issue.getNumber()); + assertThat(closedIssued.getState(), equalTo(GHIssueState.CLOSED)); + assertThat(closedIssued.getStateReason(), equalTo(GHIssueStateReason.COMPLETED)); + } + + /** + * Close issue as not planned. + * + * @throws Exception + * the exception + */ + @Test + public void closeIssueNotPlanned() throws Exception { + String name = "closeIssueNotPlanned"; + GHIssue issue = getRepository().createIssue(name).body("## test").create(); + assertThat(issue.getTitle(), equalTo(name)); + + GHIssue createdIssue = issue.getRepository().getIssue(issue.getNumber()); + + assertThat(createdIssue.getState(), equalTo(GHIssueState.OPEN)); + assertThat(createdIssue.getStateReason(), nullValue()); + + issue.close(GHIssueStateReason.NOT_PLANNED); + + GHIssue closedIssued = getRepository().getIssue(issue.getNumber()); + assertThat(closedIssued.getState(), equalTo(GHIssueState.CLOSED)); + assertThat(closedIssued.getStateReason(), equalTo(GHIssueStateReason.NOT_PLANNED)); + } + + /** + * Sets the labels. + * + * @throws Exception + * the exception + */ + @Test + // Requires push access to the test repo to pass + public void setLabels() throws Exception { + GHIssue issue = getRepository().createIssue("setLabels").body("## test").create(); + String label = "setLabels_label_name"; + issue.setLabels(label); + + Collection labels = getRepository().getIssue(issue.getNumber()).getLabels(); + assertThat(labels.size(), equalTo(1)); + GHLabel savedLabel = labels.iterator().next(); + assertThat(savedLabel.getName(), equalTo(label)); + assertThat(savedLabel.getId(), notNullValue()); + assertThat(savedLabel.getNodeId(), notNullValue()); + assertThat(savedLabel.isDefault(), is(false)); + } + + /** + * Adds the labels. + * + * @throws Exception + * the exception + */ + @Test + // Requires push access to the test repo to pass + public void addLabels() throws Exception { + GHIssue issue = getRepository().createIssue("addLabels").body("## test").create(); + String addedLabel1 = "addLabels_label_name_1"; + String addedLabel2 = "addLabels_label_name_2"; + String addedLabel3 = "addLabels_label_name_3"; + + List resultingLabels = issue.addLabels(addedLabel1); + assertThat(resultingLabels.size(), equalTo(1)); + GHLabel ghLabel = resultingLabels.get(0); + assertThat(ghLabel.getName(), equalTo(addedLabel1)); + + int requestCount = mockGitHub.getRequestCount(); + resultingLabels = issue.addLabels(addedLabel2, addedLabel3); + // multiple labels can be added with one api call + assertThat(mockGitHub.getRequestCount(), equalTo(requestCount + 1)); + + assertThat(resultingLabels.size(), equalTo(3)); + assertThat(resultingLabels, + containsInAnyOrder(hasProperty("name", equalTo(addedLabel1)), + hasProperty("name", equalTo(addedLabel2)), + hasProperty("name", equalTo(addedLabel3)))); + + // Adding a label which is already present does not throw an error + resultingLabels = issue.addLabels(ghLabel); + assertThat(resultingLabels.size(), equalTo(3)); + } + + /** + * Adds the labels concurrency issue. + * + * @throws Exception + * the exception + */ + @Disabled("Flaky under WireMock—mock sometimes returns 403 instead of expected 404") + @Test + // Requires push access to the test repo to pass + public void addLabelsConcurrencyIssue() throws Exception { + String addedLabel1 = "addLabelsConcurrencyIssue_label_name_1"; + String addedLabel2 = "addLabelsConcurrencyIssue_label_name_2"; + + GHIssue issue1 = getRepository().createIssue("addLabelsConcurrencyIssue").body("## test").create(); + issue1.getLabels(); + + GHIssue issue2 = getRepository().getIssue(issue1.getNumber()); + issue2.addLabels(addedLabel2); + + Collection labels = issue1.addLabels(addedLabel1); + + assertThat(labels.size(), equalTo(2)); + assertThat(labels, + containsInAnyOrder(hasProperty("name", equalTo(addedLabel1)), + hasProperty("name", equalTo(addedLabel2)))); + } + /** * Removes the labels. * @@ -329,29 +336,21 @@ public void setAssignee() throws Exception { } /** - * Sets the labels. + * Gets the user test. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - // Requires push access to the test repo to pass - public void setLabels() throws Exception { - GHIssue issue = getRepository().createIssue("setLabels").body("## test").create(); - String label = "setLabels_label_name"; - issue.setLabels(label); - - Collection labels = getRepository().getIssue(issue.getNumber()).getLabels(); - assertThat(labels.size(), equalTo(1)); - GHLabel savedLabel = labels.iterator().next(); - assertThat(savedLabel.getName(), equalTo(label)); - assertThat(savedLabel.getId(), notNullValue()); - assertThat(savedLabel.getNodeId(), notNullValue()); - assertThat(savedLabel.isDefault(), is(false)); - } + public void getUserTest() throws IOException { + GHIssue issue = getRepository().createIssue("getUserTest").create(); + GHIssue issueSingle = getRepository().getIssue(issue.getNumber()); + assertThat(issueSingle.getUser().root(), notNullValue()); - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("GHIssueTest"); + PagedIterable ghIssues = getRepository().queryIssues().state(GHIssueState.OPEN).list(); + for (GHIssue otherIssue : ghIssues) { + assertThat(otherIssue.getUser().root(), notNullValue()); + } } /** @@ -365,4 +364,8 @@ protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("GHIssueTest"); + } + } diff --git a/src/test/java/org/kohsuke/github/GHLicenseTest.java b/src/test/java/org/kohsuke/github/GHLicenseTest.java index 63e37b5f02..89580309b6 100644 --- a/src/test/java/org/kohsuke/github/GHLicenseTest.java +++ b/src/test/java/org/kohsuke/github/GHLicenseTest.java @@ -47,26 +47,62 @@ public GHLicenseTest() { } /** - * Accesses the 'kohsuke/github-api' repo using {@link GitHub#getRepository(String)} and then calls - * {@link GHRepository#getLicense()} and checks that certain properties are correct. + * Basic test to ensure that the list of licenses from {@link GitHub#listLicenses()} is returned. * * @throws IOException * if test fails */ @Test - public void checkRepositoryFullLicense() throws IOException { - GHRepository repo = gitHub.getRepository("hub4j/github-api"); - GHLicense license = repo.getLicense(); - assertThat("The license is populated", license, notNullValue()); - assertThat("The key is correct", license.getKey(), equalTo("mit")); - assertThat("The SPDX ID is correct", license.getSpdxId(), is(equalTo("MIT"))); + public void listLicenses() throws IOException { + Iterable licenses = gitHub.listLicenses(); + assertThat(licenses, is(not(emptyIterable()))); + } + + /** + * Tests that {@link GitHub#listLicenses()} returns the MIT license in the expected manner. + * + * @throws IOException + * if test fails + */ + @Test + public void listLicensesCheckIndividualLicense() throws IOException { + PagedIterable licenses = gitHub.listLicenses(); + for (GHLicense lic : licenses) { + if (lic.getKey().equals("mit")) { + assertThat(lic.getUrl(), equalTo(new URL(mockGitHub.apiServer().baseUrl() + "/licenses/mit"))); + return; + } + } + fail("The MIT license was not found"); + } + + /** + * Checks that the request for an individual license using {@link GitHub#getLicense(String)} returns expected values + * (not all properties are checked). + * + * @throws IOException + * if test fails + */ + @Test + public void getLicense() throws IOException { + String key = "mit"; + GHLicense license = gitHub.getLicense(key); + assertThat(license, notNullValue()); assertThat("The name is correct", license.getName(), equalTo("MIT License")); - assertThat("The URL is correct", - license.getUrl(), - equalTo(new URL(mockGitHub.apiServer().baseUrl() + "/licenses/mit"))); + assertThat("The SPDX ID is correct", license.getSpdxId(), is(equalTo("MIT"))); assertThat("The HTML URL is correct", license.getHtmlUrl(), equalTo(new URL("http://choosealicense.com/licenses/mit/"))); + assertThat(license.getBody(), startsWith("MIT License\n" + "\n" + "Copyright (c) [year] [fullname]\n\n")); + assertThat(license.getForbidden(), is(empty())); + assertThat(license.getPermitted(), is(empty())); + assertThat(license.getRequired(), is(empty())); + assertThat(license.getImplementation(), + equalTo("Create a text file (typically named LICENSE or LICENSE.txt) in the root of your source code and copy the text of the license into the file. Replace [year] with the current year and [fullname] with the name (or names) of the copyright holders.")); + assertThat(license.getCategory(), nullValue()); + assertThat(license.isFeatured(), equalTo(true)); + assertThat(license.equals(null), equalTo(false)); + assertThat(license.equals(gitHub.getLicense(key)), equalTo(true)); } /** @@ -108,46 +144,6 @@ public void checkRepositoryLicenseAtom() throws IOException { equalTo(new URL(mockGitHub.apiServer().baseUrl() + "/licenses/mit"))); } - /** - * Accesses the 'pomes/pomes' repo using {@link GitHub#getRepository(String)} and then calls - * {@link GHRepository#getLicenseContent()} and checks that certain properties are correct. - * - * @throws IOException - * if test fails - */ - @Test - public void checkRepositoryLicenseContent() throws IOException { - GHRepository repo = gitHub.getRepository("pomes/pomes"); - GHContent content = repo.getLicenseContent(); - assertThat("The license content is populated", content, notNullValue()); - assertThat("The type is 'file'", content.getType(), equalTo("file")); - assertThat("The license file is 'LICENSE'", content.getName(), equalTo("LICENSE")); - - if (content.getEncoding().equals("base64")) { - String licenseText = new String(IOUtils.toByteArray(content.read())); - assertThat("The license appears to be an Apache License", licenseText.contains("Apache License")); - } else { - fail("Expected the license to be Base64 encoded but instead it was " + content.getEncoding()); - } - } - - /** - * Accesses the 'bndtools/bnd' repo using {@link GitHub#getRepository(String)} and then calls - * {@link GHRepository#getLicense()}. The description is null due to multiple licences - * - * @throws IOException - * if test fails - */ - @Test - public void checkRepositoryLicenseForIndeterminate() throws IOException { - GHRepository repo = gitHub.getRepository("bndtools/bnd"); - GHLicense license = repo.getLicense(); - assertThat("The license is populated", license, notNullValue()); - assertThat(license.getKey(), equalTo("other")); - assertThat(license.getDescription(), is(nullValue())); - assertThat(license.getUrl(), is(nullValue())); - } - /** * Accesses the 'pomes/pomes' repo using {@link GitHub#getRepository(String)} and checks that the license is * correct. @@ -183,58 +179,65 @@ public void checkRepositoryWithoutLicense() throws IOException { } /** - * Checks that the request for an individual license using {@link GitHub#getLicense(String)} returns expected values - * (not all properties are checked). + * Accesses the 'kohsuke/github-api' repo using {@link GitHub#getRepository(String)} and then calls + * {@link GHRepository#getLicense()} and checks that certain properties are correct. * * @throws IOException * if test fails */ @Test - public void getLicense() throws IOException { - String key = "mit"; - GHLicense license = gitHub.getLicense(key); - assertThat(license, notNullValue()); - assertThat("The name is correct", license.getName(), equalTo("MIT License")); + public void checkRepositoryFullLicense() throws IOException { + GHRepository repo = gitHub.getRepository("hub4j/github-api"); + GHLicense license = repo.getLicense(); + assertThat("The license is populated", license, notNullValue()); + assertThat("The key is correct", license.getKey(), equalTo("mit")); assertThat("The SPDX ID is correct", license.getSpdxId(), is(equalTo("MIT"))); + assertThat("The name is correct", license.getName(), equalTo("MIT License")); + assertThat("The URL is correct", + license.getUrl(), + equalTo(new URL(mockGitHub.apiServer().baseUrl() + "/licenses/mit"))); assertThat("The HTML URL is correct", license.getHtmlUrl(), equalTo(new URL("http://choosealicense.com/licenses/mit/"))); - assertThat(license.getBody(), startsWith("MIT License\n" + "\n" + "Copyright (c) [year] [fullname]\n\n")); - assertThat(license.getForbidden(), is(empty())); - assertThat(license.getPermitted(), is(empty())); - assertThat(license.getRequired(), is(empty())); - assertThat(license.getImplementation(), - equalTo("Create a text file (typically named LICENSE or LICENSE.txt) in the root of your source code and copy the text of the license into the file. Replace [year] with the current year and [fullname] with the name (or names) of the copyright holders.")); - assertThat(license.getCategory(), nullValue()); - assertThat(license.isFeatured(), equalTo(true)); - assertThat(license.equals(null), equalTo(false)); - assertThat(license.equals(gitHub.getLicense(key)), equalTo(true)); } /** - * Basic test to ensure that the list of licenses from {@link GitHub#listLicenses()} is returned. + * Accesses the 'pomes/pomes' repo using {@link GitHub#getRepository(String)} and then calls + * {@link GHRepository#getLicenseContent()} and checks that certain properties are correct. + * + * @throws IOException + * if test fails */ @Test - public void listLicenses() { - Iterable licenses = gitHub.listLicenses(); - assertThat(licenses, is(not(emptyIterable()))); + public void checkRepositoryLicenseContent() throws IOException { + GHRepository repo = gitHub.getRepository("pomes/pomes"); + GHContent content = repo.getLicenseContent(); + assertThat("The license content is populated", content, notNullValue()); + assertThat("The type is 'file'", content.getType(), equalTo("file")); + assertThat("The license file is 'LICENSE'", content.getName(), equalTo("LICENSE")); + + if (content.getEncoding().equals("base64")) { + String licenseText = new String(IOUtils.toByteArray(content.read())); + assertThat("The license appears to be an Apache License", licenseText.contains("Apache License")); + } else { + fail("Expected the license to be Base64 encoded but instead it was " + content.getEncoding()); + } } /** - * Tests that {@link GitHub#listLicenses()} returns the MIT license in the expected manner. + * Accesses the 'bndtools/bnd' repo using {@link GitHub#getRepository(String)} and then calls + * {@link GHRepository#getLicense()}. The description is null due to multiple licences * * @throws IOException * if test fails */ @Test - public void listLicensesCheckIndividualLicense() throws IOException { - PagedIterable licenses = gitHub.listLicenses(); - for (GHLicense lic : licenses) { - if (lic.getKey().equals("mit")) { - assertThat(lic.getUrl(), equalTo(new URL(mockGitHub.apiServer().baseUrl() + "/licenses/mit"))); - return; - } - } - fail("The MIT license was not found"); + public void checkRepositoryLicenseForIndeterminate() throws IOException { + GHRepository repo = gitHub.getRepository("bndtools/bnd"); + GHLicense license = repo.getLicense(); + assertThat("The license is populated", license, notNullValue()); + assertThat(license.getKey(), equalTo("other")); + assertThat(license.getDescription(), is(nullValue())); + assertThat(license.getUrl(), is(nullValue())); } } diff --git a/src/test/java/org/kohsuke/github/GHMarketplacePlanTest.java b/src/test/java/org/kohsuke/github/GHMarketplacePlanTest.java index 02edb19a9e..ef8b5690cd 100644 --- a/src/test/java/org/kohsuke/github/GHMarketplacePlanTest.java +++ b/src/test/java/org/kohsuke/github/GHMarketplacePlanTest.java @@ -20,93 +20,35 @@ */ public class GHMarketplacePlanTest extends AbstractGitHubWireMockTest { - static void testMarketplaceAccount(GHMarketplaceAccountPlan account) { - // Non-nullable fields - assertThat(account.getLogin(), notNullValue()); - assertThat(account.getUrl(), notNullValue()); - assertThat(account.getType(), notNullValue()); - assertThat(account.getMarketplacePurchase(), notNullValue()); - testMarketplacePurchase(account.getMarketplacePurchase()); - - // primitive fields - assertThat(account.getId(), not(0L)); - - /* logical combination tests */ - // Rationale: organization_billing_email is only set when account type is ORGANIZATION. - if (account.getType() == ORGANIZATION) - assertThat(account.getOrganizationBillingEmail(), notNullValue()); - else - assertThat(account.getOrganizationBillingEmail(), nullValue()); - - // Rationale: marketplace_pending_change isn't always set... This is what GitHub says about it: - // "When someone submits a plan change that won't be processed until the end of their billing cycle, - // you will also see the upcoming pending change." - if (account.getMarketplacePendingChange() != null) - testMarketplacePendingChange(account.getMarketplacePendingChange()); - } - - static void testMarketplacePendingChange(GHMarketplacePendingChange marketplacePendingChange) { - // Non-nullable fields - assertThat(marketplacePendingChange.getEffectiveDate(), notNullValue()); - testMarketplacePlan(marketplacePendingChange.getPlan()); - - // primitive fields - assertThat(marketplacePendingChange.getId(), not(0L)); - - /* logical combination tests */ - // Rationale: if price model is PER_UNIT then unit_count can't be null - if (marketplacePendingChange.getPlan().getPriceModel() == GHMarketplacePriceModel.PER_UNIT) - assertThat(marketplacePendingChange.getUnitCount(), notNullValue()); - else - assertThat(marketplacePendingChange.getUnitCount(), nullValue()); - - } - - static void testMarketplacePlan(GHMarketplacePlan plan) { - // Non-nullable fields - assertThat(plan.getUrl(), notNullValue()); - assertThat(plan.getAccountsUrl(), notNullValue()); - assertThat(plan.getName(), notNullValue()); - assertThat(plan.getDescription(), notNullValue()); - assertThat(plan.getPriceModel(), notNullValue()); - assertThat(plan.getState(), notNullValue()); - - // primitive fields - assertThat(plan.getId(), not(0L)); - assertThat(plan.getNumber(), not(0L)); - assertThat(plan.getMonthlyPriceInCents(), greaterThanOrEqualTo(0L)); - - // list - assertThat(plan.getBullets().size(), Matchers.in(Arrays.asList(2, 3))); + /** + * Create default GHMarketplacePlanTest instance + */ + public GHMarketplacePlanTest() { } - static void testMarketplacePurchase(GHMarketplacePurchase marketplacePurchase) { - // Non-nullable fields - assertThat(marketplacePurchase.getBillingCycle(), notNullValue()); - assertThat(marketplacePurchase.getNextBillingDate(), notNullValue()); - assertThat(marketplacePurchase.getUpdatedAt(), notNullValue()); - testMarketplacePlan(marketplacePurchase.getPlan()); - - /* logical combination tests */ - // Rationale: if onFreeTrial is true, then we should see free_trial_ends_on property set to something - // different than null - if (marketplacePurchase.isOnFreeTrial()) - assertThat(marketplacePurchase.getFreeTrialEndsOn(), notNullValue()); - else - assertThat(marketplacePurchase.getFreeTrialEndsOn(), nullValue()); - - // Rationale: if price model is PER_UNIT then unit_count can't be null - if (marketplacePurchase.getPlan().getPriceModel() == GHMarketplacePriceModel.PER_UNIT) - assertThat(marketplacePurchase.getUnitCount(), notNullValue()); - else - assertThat(marketplacePurchase.getUnitCount(), Matchers.anyOf(nullValue(), is(1L))); - + /** + * Gets the git hub builder. + * + * @return the git hub builder + */ + protected GitHubBuilder getGitHubBuilder() { + return super.getGitHubBuilder() + // ensure that only JWT will be used against the tests below + .withOAuthToken(null, null) + .withJwtToken("bogus"); } /** - * Create default GHMarketplacePlanTest instance + * List marketplace plans. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ - public GHMarketplacePlanTest() { + @Test + public void listMarketplacePlans() throws IOException { + List plans = gitHub.listMarketplacePlans().toList(); + assertThat(plans.size(), equalTo(3)); + plans.forEach(GHMarketplacePlanTest::testMarketplacePlan); } /** @@ -169,29 +111,87 @@ public void listAccountsWithSortAndDirection() throws IOException { } - /** - * List marketplace plans. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void listMarketplacePlans() throws IOException { - List plans = gitHub.listMarketplacePlans().toList(); - assertThat(plans.size(), equalTo(3)); - plans.forEach(GHMarketplacePlanTest::testMarketplacePlan); + static void testMarketplacePlan(GHMarketplacePlan plan) { + // Non-nullable fields + assertThat(plan.getUrl(), notNullValue()); + assertThat(plan.getAccountsUrl(), notNullValue()); + assertThat(plan.getName(), notNullValue()); + assertThat(plan.getDescription(), notNullValue()); + assertThat(plan.getPriceModel(), notNullValue()); + assertThat(plan.getState(), notNullValue()); + + // primitive fields + assertThat(plan.getId(), not(0L)); + assertThat(plan.getNumber(), not(0L)); + assertThat(plan.getMonthlyPriceInCents(), greaterThanOrEqualTo(0L)); + + // list + assertThat(plan.getBullets().size(), Matchers.in(Arrays.asList(2, 3))); } - /** - * Gets the git hub builder. - * - * @return the git hub builder - */ - protected GitHubBuilder getGitHubBuilder() { - return super.getGitHubBuilder() - // ensure that only JWT will be used against the tests below - .withOAuthToken(null, null) - .withJwtToken("bogus"); + static void testMarketplaceAccount(GHMarketplaceAccountPlan account) { + // Non-nullable fields + assertThat(account.getLogin(), notNullValue()); + assertThat(account.getUrl(), notNullValue()); + assertThat(account.getType(), notNullValue()); + assertThat(account.getMarketplacePurchase(), notNullValue()); + testMarketplacePurchase(account.getMarketplacePurchase()); + + // primitive fields + assertThat(account.getId(), not(0L)); + + /* logical combination tests */ + // Rationale: organization_billing_email is only set when account type is ORGANIZATION. + if (account.getType() == ORGANIZATION) + assertThat(account.getOrganizationBillingEmail(), notNullValue()); + else + assertThat(account.getOrganizationBillingEmail(), nullValue()); + + // Rationale: marketplace_pending_change isn't always set... This is what GitHub says about it: + // "When someone submits a plan change that won't be processed until the end of their billing cycle, + // you will also see the upcoming pending change." + if (account.getMarketplacePendingChange() != null) + testMarketplacePendingChange(account.getMarketplacePendingChange()); + } + + static void testMarketplacePurchase(GHMarketplacePurchase marketplacePurchase) { + // Non-nullable fields + assertThat(marketplacePurchase.getBillingCycle(), notNullValue()); + assertThat(marketplacePurchase.getNextBillingDate(), notNullValue()); + assertThat(marketplacePurchase.getUpdatedAt(), notNullValue()); + testMarketplacePlan(marketplacePurchase.getPlan()); + + /* logical combination tests */ + // Rationale: if onFreeTrial is true, then we should see free_trial_ends_on property set to something + // different than null + if (marketplacePurchase.isOnFreeTrial()) + assertThat(marketplacePurchase.getFreeTrialEndsOn(), notNullValue()); + else + assertThat(marketplacePurchase.getFreeTrialEndsOn(), nullValue()); + + // Rationale: if price model is PER_UNIT then unit_count can't be null + if (marketplacePurchase.getPlan().getPriceModel() == GHMarketplacePriceModel.PER_UNIT) + assertThat(marketplacePurchase.getUnitCount(), notNullValue()); + else + assertThat(marketplacePurchase.getUnitCount(), Matchers.anyOf(nullValue(), is(1L))); + + } + + static void testMarketplacePendingChange(GHMarketplacePendingChange marketplacePendingChange) { + // Non-nullable fields + assertThat(marketplacePendingChange.getEffectiveDate(), notNullValue()); + testMarketplacePlan(marketplacePendingChange.getPlan()); + + // primitive fields + assertThat(marketplacePendingChange.getId(), not(0L)); + + /* logical combination tests */ + // Rationale: if price model is PER_UNIT then unit_count can't be null + if (marketplacePendingChange.getPlan().getPriceModel() == GHMarketplacePriceModel.PER_UNIT) + assertThat(marketplacePendingChange.getUnitCount(), notNullValue()); + else + assertThat(marketplacePendingChange.getUnitCount(), nullValue()); + } } diff --git a/src/test/java/org/kohsuke/github/GHMilestoneTest.java b/src/test/java/org/kohsuke/github/GHMilestoneTest.java index b7e6994d3e..78867c4cd3 100644 --- a/src/test/java/org/kohsuke/github/GHMilestoneTest.java +++ b/src/test/java/org/kohsuke/github/GHMilestoneTest.java @@ -5,10 +5,10 @@ import org.junit.Test; import java.io.IOException; -import java.time.Instant; import java.util.Date; import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.containsString; // TODO: Auto-generated Javadoc /** @@ -46,6 +46,41 @@ public void cleanUp() throws Exception { } } + /** + * Test update milestone. + * + * @throws Exception + * the exception + */ + @Test + public void testUpdateMilestone() throws Exception { + GHRepository repo = getRepository(); + GHMilestone milestone = repo.createMilestone("Original Title", "To test the update methods"); + + String NEW_TITLE = "Updated Title"; + String NEW_DESCRIPTION = "Updated Description"; + Date NEW_DUE_DATE = GitHubClient.parseDate("2020-10-05T13:00:00Z"); + Date OUTPUT_DUE_DATE = GitHubClient.parseDate("2020-10-05T07:00:00Z"); + + milestone.setTitle(NEW_TITLE); + milestone.setDescription(NEW_DESCRIPTION); + milestone.setDueOn(NEW_DUE_DATE); + + // Force reload. + milestone = repo.getMilestone(milestone.getNumber()); + + assertThat(milestone.getTitle(), equalTo(NEW_TITLE)); + assertThat(milestone.getDescription(), equalTo(NEW_DESCRIPTION)); + + // The time is truncated when sent to the server, but still part of the returned value + // 07:00 midnight PDT + assertThat(milestone.getDueOn(), equalTo(OUTPUT_DUE_DATE)); + assertThat(milestone.getHtmlUrl().toString(), containsString("/hub4j-test-org/github-api/milestone/")); + assertThat(milestone.getUrl().toString(), containsString("/repos/hub4j-test-org/github-api/milestones/")); + assertThat(milestone.getClosedIssues(), equalTo(0)); + assertThat(milestone.getOpenIssues(), equalTo(0)); + } + /** * Test unset milestone. * @@ -93,46 +128,6 @@ public void testUnsetMilestoneFromPullRequest() throws IOException { assertThat(p.getMilestone(), nullValue()); } - /** - * Test update milestone. - * - * @throws Exception - * the exception - */ - @Test - public void testUpdateMilestone() throws Exception { - GHRepository repo = getRepository(); - GHMilestone milestone = repo.createMilestone("Original Title", "To test the update methods"); - - String NEW_TITLE = "Updated Title"; - String NEW_DESCRIPTION = "Updated Description"; - Date NEW_DUE_DATE = Date.from(GitHubClient.parseInstant("2020-10-05T13:00:00Z")); - Instant OUTPUT_DUE_DATE = GitHubClient.parseInstant("2020-10-05T07:00:00Z"); - - milestone.setTitle(NEW_TITLE); - milestone.setDescription(NEW_DESCRIPTION); - milestone.setDueOn(NEW_DUE_DATE); - - // Force reload. - milestone = repo.getMilestone(milestone.getNumber()); - - assertThat(milestone.getTitle(), equalTo(NEW_TITLE)); - assertThat(milestone.getDescription(), equalTo(NEW_DESCRIPTION)); - - // The time is truncated when sent to the server, but still part of the returned value - // 07:00 midnight PDT - assertThat(milestone.getDueOn(), equalTo(OUTPUT_DUE_DATE)); - assertThat(milestone.getClosedAt(), nullValue()); - assertThat(milestone.getHtmlUrl().toString(), containsString("/hub4j-test-org/github-api/milestone/")); - assertThat(milestone.getUrl().toString(), containsString("/repos/hub4j-test-org/github-api/milestones/")); - assertThat(milestone.getClosedIssues(), equalTo(0)); - assertThat(milestone.getOpenIssues(), equalTo(0)); - } - - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); - } - /** * Gets the repository. * @@ -143,4 +138,8 @@ private GHRepository getRepository(GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } } diff --git a/src/test/java/org/kohsuke/github/GHOrganizationTest.java b/src/test/java/org/kohsuke/github/GHOrganizationTest.java index 89388427b4..7457869b1d 100644 --- a/src/test/java/org/kohsuke/github/GHOrganizationTest.java +++ b/src/test/java/org/kohsuke/github/GHOrganizationTest.java @@ -23,19 +23,29 @@ */ public class GHOrganizationTest extends AbstractGitHubWireMockTest { - /** The Constant GITHUB_API_TEMPLATE_TEST. */ - public static final String GITHUB_API_TEMPLATE_TEST = "github-api-template-test"; + /** + * Create default GHOrganizationTest instance + */ + public GHOrganizationTest() { + } /** The Constant GITHUB_API_TEST. */ public static final String GITHUB_API_TEST = "github-api-test"; + /** The Constant GITHUB_API_TEMPLATE_TEST. */ + public static final String GITHUB_API_TEMPLATE_TEST = "github-api-template-test"; + /** The Constant TEAM_NAME_CREATE. */ public static final String TEAM_NAME_CREATE = "create-team-test"; /** - * Create default GHOrganizationTest instance + * Enable response templating to allow support validating pagination of external groups + * + * @return the updated WireMock options */ - public GHOrganizationTest() { + @Override + protected WireMockConfiguration getWireMockOptions() { + return super.getWireMockOptions().extensions(templating.newResponseTransformer()); } /** @@ -60,46 +70,6 @@ public void cleanUpTeam() throws IOException { getNonRecordingGitHub().getOrganization(GITHUB_API_TEST_ORG).enableOrganizationProjects(true); } - /** - * Test are organization projects enabled. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testAreOrganizationProjectsEnabled() throws IOException { - // Arrange - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - - // Act - boolean result = org.areOrganizationProjectsEnabled(); - - // Assert - assertThat(result, is(true)); - } - - /** - * Test create all args team. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testCreateAllArgsTeam() throws IOException { - String REPO_NAME = "github-api"; - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - - GHTeam team = org.createTeam(TEAM_NAME_CREATE) - .description("Team description") - .maintainers("bitwiseman") - .repositories(REPO_NAME) - .privacy(GHTeam.Privacy.CLOSED) - .parentTeamId(3617900) - .create(); - assertThat(team.getDescription(), equalTo("Team description")); - assertThat(team.getPrivacy(), equalTo(GHTeam.Privacy.CLOSED)); - } - /** * Test create repository. * @@ -120,43 +90,6 @@ public void testCreateRepository() throws IOException { assertThat(repository, notNullValue()); } - /** - * Test create repository with template repository null. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testCreateRepositoryFromTemplateRepositoryNull() throws IOException { - cleanupRepository(GITHUB_API_TEST_ORG + '/' + GITHUB_API_TEST); - - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - assertThrows(NullPointerException.class, () -> { - org.createRepository(GITHUB_API_TEST).fromTemplateRepository(null).owner(GITHUB_API_TEST_ORG).create(); - }); - } - - /** - * Test create repository when repository template is not a template. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testCreateRepositoryWhenRepositoryTemplateIsNotATemplate() throws IOException { - cleanupRepository(GITHUB_API_TEST_ORG + '/' + GITHUB_API_TEST); - - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHRepository templateRepository = org.getRepository(GITHUB_API_TEMPLATE_TEST); - - assertThrows(IllegalArgumentException.class, () -> { - org.createRepository(GITHUB_API_TEST) - .fromTemplateRepository(templateRepository) - .owner(GITHUB_API_TEST_ORG) - .create(); - }); - } - /** * Test create repository with auto initialization. * @@ -265,289 +198,438 @@ public void testCreateRepositoryWithTemplateAndGHRepository() throws IOException } /** - * Test create team. + * Test create repository with template repository null. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCreateTeam() throws IOException { - String REPO_NAME = "github-api"; - String DEFAULT_PERMISSION = Permission.PULL.toString().toLowerCase(); - - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHRepository repo = org.getRepository(REPO_NAME); - - // Create team with no permission field. Verify that default permission is pull - GHTeam team = org.createTeam(TEAM_NAME_CREATE).repositories(repo.getFullName()).create(); - assertThat(team.getRepositories().containsKey(REPO_NAME), is(true)); - assertThat(team.getPermission(), equalTo(DEFAULT_PERMISSION)); - } - - /** - * Test create team with null perm. - * - * @throws Exception - * the exception - */ - @Test - public void testCreateTeamWithNullPerm() throws Exception { - String REPO_NAME = "github-api"; + public void testCreateRepositoryFromTemplateRepositoryNull() throws IOException { + cleanupRepository(GITHUB_API_TEST_ORG + '/' + GITHUB_API_TEST); GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHRepository repo = org.getRepository(REPO_NAME); - - // Create team with access to repository. Check access was granted. - GHTeam team = org.createTeam(TEAM_NAME_CREATE).create(); - - team.add(repo); - - assertThat( - repo.getTeams() - .stream() - .filter(t -> TEAM_NAME_CREATE.equals(t.getName())) - .findFirst() - .get() - .getPermission(), - equalTo(Permission.PULL.toString().toLowerCase())); + assertThrows(NullPointerException.class, () -> { + org.createRepository(GITHUB_API_TEST).fromTemplateRepository(null).owner(GITHUB_API_TEST_ORG).create(); + }); } /** - * Test create team with repo access. + * Test create repository when repository template is not a template. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCreateTeamWithRepoAccess() throws IOException { - String REPO_NAME = "github-api"; + public void testCreateRepositoryWhenRepositoryTemplateIsNotATemplate() throws IOException { + cleanupRepository(GITHUB_API_TEST_ORG + '/' + GITHUB_API_TEST); GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHRepository repo = org.getRepository(REPO_NAME); + GHRepository templateRepository = org.getRepository(GITHUB_API_TEMPLATE_TEST); - // Create team with access to repository. Check access was granted. - GHTeam team = org.createTeam(TEAM_NAME_CREATE) - .repositories(repo.getFullName()) - .permission(Permission.PUSH) - .create(); - assertThat(team.getRepositories().containsKey(REPO_NAME), is(true)); - assertThat(team.getPermission(), equalTo(Permission.PUSH.toString().toLowerCase())); + assertThrows(IllegalArgumentException.class, () -> { + org.createRepository(GITHUB_API_TEST) + .fromTemplateRepository(templateRepository) + .owner(GITHUB_API_TEST_ORG) + .create(); + }); } /** - * Test create team with repo perm. + * Test invite user. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testCreateTeamWithRepoPerm() throws Exception { - String REPO_NAME = "github-api"; - + public void testInviteUser() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHRepository repo = org.getRepository(REPO_NAME); + GHUser user = gitHub.getUser("martinvanzijl2"); - // Create team with access to repository. Check access was granted. - GHTeam team = org.createTeam(TEAM_NAME_CREATE).create(); + // First remove the user + if (org.hasMember(user)) { + org.remove(user); + } - team.add(repo, GHOrganization.RepositoryRole.from(Permission.PUSH)); + // Then invite the user again + org.add(user, GHOrganization.Role.MEMBER); - assertThat( - repo.getTeams() - .stream() - .filter(t -> TEAM_NAME_CREATE.equals(t.getName())) - .findFirst() - .get() - .getPermission(), - equalTo(Permission.PUSH.toString().toLowerCase())); + // Now the user has to accept the invitation + // Can this be automated? + // user.acceptInvitationTo(org); // ? + // Check the invitation has worked. + // assertTrue(org.hasMember(user)); } /** - * Test create team with repo role. + * Test get user membership * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCreateTeamWithRepoRole() throws IOException { - String REPO_NAME = "github-api"; - - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHRepository repo = org.getRepository(REPO_NAME); - - // Create team with access to repository. Check access was granted. - GHTeam team = org.createTeam(TEAM_NAME_CREATE).create(); + public void testGetMembership() throws IOException { + GHOrganization org = gitHub.getOrganization("hub4j-test-org"); - RepositoryRole role = RepositoryRole.from(Permission.TRIAGE); - team.add(repo, role); + GHMembership membership = org.getMembership("fv316"); - // 'getPermission' does not return triage even though the UI shows that value - // assertThat( - // repo.getTeams() - // .stream() - // .filter(t -> TEAM_NAME_CREATE.equals(t.getName())) - // .findFirst() - // .get() - // .getPermission(), - // equalTo(role.toString())); + assertThat(membership, notNullValue()); + assertThat(membership.getRole(), equalTo(GHMembership.Role.ADMIN)); + assertThat(membership.getState(), equalTo(GHMembership.State.ACTIVE)); + assertThat(membership.getUser().getLogin(), equalTo("fv316")); + assertThat(membership.getOrganization().login, equalTo("hub4j-test-org")); } + /** - * Test create visible team. + * Test list members with filter. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testCreateVisibleTeam() throws IOException { + public void testListMembersWithFilter() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHTeam team = org.createTeam(TEAM_NAME_CREATE).privacy(GHTeam.Privacy.CLOSED).create(); - assertThat(team.getPrivacy(), equalTo(GHTeam.Privacy.CLOSED)); + List admins = org.listMembersWithFilter("all").toList(); + + assertThat(admins, notNullValue()); + // In case more are added in the future + assertThat(admins.size(), greaterThanOrEqualTo(12)); + assertThat(admins.stream().map(GHUser::getLogin).collect(Collectors.toList()), + hasItems("alexanderrtaylor", + "asthinasthi", + "bitwiseman", + "farmdawgnation", + "halkeye", + "jberglund-BSFT", + "kohsuke", + "kohsuke2", + "martinvanzijl", + "PauloMigAlmeida", + "Sage-Pierce", + "timja")); } /** - * Test enable organization projects. + * Test list members with role. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testEnableOrganizationProjects() throws IOException { - // Arrange + public void testListMembersWithRole() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - // Act - org.enableOrganizationProjects(false); + List admins = org.listMembersWithRole("admin").toList(); - // Assert - assertThat(org.areOrganizationProjectsEnabled(), is(false)); + assertThat(admins, notNullValue()); + // In case more are added in the future + assertThat(admins.size(), greaterThanOrEqualTo(12)); + assertThat(admins.stream().map(GHUser::getLogin).collect(Collectors.toList()), + hasItems("alexanderrtaylor", + "asthinasthi", + "bitwiseman", + "farmdawgnation", + "halkeye", + "jberglund-BSFT", + "kohsuke", + "kohsuke2", + "martinvanzijl", + "PauloMigAlmeida", + "Sage-Pierce", + "timja")); } /** - * Test get external group + * Test list security managers. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetExternalGroup() throws IOException { + public void testListSecurityManagers() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHExternalGroup group = org.getExternalGroup(467431L); + List securityManagers = org.listSecurityManagers().toList(); - assertThat(group, not(isExternalGroupSummary())); + assertThat(securityManagers, notNullValue()); + // In case more are added in the future + assertThat(securityManagers.size(), greaterThanOrEqualTo(1)); + assertThat(securityManagers.stream().map(GHTeam::getName).collect(Collectors.toList()), + hasItems("security team")); + } - assertThat(group.getId(), equalTo(467431L)); - assertThat(group.getName(), equalTo("acme-developers")); - assertThat(group.getUpdatedAt(), notNullValue()); + /** + * Test list outside collaborators. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testListOutsideCollaborators() throws IOException { + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - assertThat(group.getMembers(), notNullValue()); - assertThat(membersSummary(group), - hasItems("158311279:john-doe_acme:John Doe:john.doe@acme.corp", - "166731041:jane-doe_acme:Jane Doe:jane.doe@acme.corp")); + List admins = org.listOutsideCollaborators().toList(); - assertThat(group.getTeams(), notNullValue()); - assertThat(teamSummary(group), hasItems("9891173:ACME-DEVELOPERS")); + assertThat(admins, notNullValue()); + // In case more are added in the future + assertThat(admins.size(), greaterThanOrEqualTo(12)); + assertThat(admins.stream().map(GHUser::getLogin).collect(Collectors.toList()), + hasItems("alexanderrtaylor", + "asthinasthi", + "bitwiseman", + "farmdawgnation", + "halkeye", + "jberglund-BSFT", + "kohsuke", + "kohsuke2", + "martinvanzijl", + "PauloMigAlmeida", + "Sage-Pierce", + "timja")); + } + /** + * Test list outside collaborators with filter. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testListOutsideCollaboratorsWithFilter() throws IOException { + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + + List admins = org.listOutsideCollaboratorsWithFilter("all").toList(); + + assertThat(admins, notNullValue()); + // In case more are added in the future + assertThat(admins.size(), greaterThanOrEqualTo(12)); + assertThat(admins.stream().map(GHUser::getLogin).collect(Collectors.toList()), + hasItems("alexanderrtaylor", + "asthinasthi", + "bitwiseman", + "farmdawgnation", + "halkeye", + "jberglund-BSFT", + "kohsuke", + "kohsuke2", + "martinvanzijl", + "PauloMigAlmeida", + "Sage-Pierce", + "timja")); } /** - * Test get external group for not enterprise managed organization + * Test create team with repo access. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetExternalGroupNotEnterpriseManagedOrganization() throws IOException { + public void testCreateTeamWithRepoAccess() throws IOException { + String REPO_NAME = "github-api"; + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHRepository repo = org.getRepository(REPO_NAME); - final GHIOException failure = assertThrows(GHNotExternallyManagedEnterpriseException.class, - () -> org.getExternalGroup(12345)); + // Create team with access to repository. Check access was granted. + GHTeam team = org.createTeam(TEAM_NAME_CREATE) + .repositories(repo.getFullName()) + .permission(Permission.PUSH) + .create(); + assertThat(team.getRepositories().containsKey(REPO_NAME), is(true)); + assertThat(team.getPermission(), equalTo(Permission.PUSH.toString().toLowerCase())); + } - assertThat(failure.getMessage(), equalTo("Could not retrieve organization external group")); + /** + * Test create team with null perm. + * + * @throws Exception + * the exception + */ + @Test + public void testCreateTeamWithNullPerm() throws Exception { + String REPO_NAME = "github-api"; + + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHRepository repo = org.getRepository(REPO_NAME); + + // Create team with access to repository. Check access was granted. + GHTeam team = org.createTeam(TEAM_NAME_CREATE).create(); + + team.add(repo); + + assertThat( + repo.getTeams() + .stream() + .filter(t -> TEAM_NAME_CREATE.equals(t.getName())) + .findFirst() + .get() + .getPermission(), + equalTo(Permission.PULL.toString().toLowerCase())); } /** - * Test get user membership + * Test create team with repo perm. + * + * @throws Exception + * the exception + */ + @Test + public void testCreateTeamWithRepoPerm() throws Exception { + String REPO_NAME = "github-api"; + + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHRepository repo = org.getRepository(REPO_NAME); + + // Create team with access to repository. Check access was granted. + GHTeam team = org.createTeam(TEAM_NAME_CREATE).create(); + + team.add(repo, GHOrganization.RepositoryRole.from(Permission.PUSH)); + + assertThat( + repo.getTeams() + .stream() + .filter(t -> TEAM_NAME_CREATE.equals(t.getName())) + .findFirst() + .get() + .getPermission(), + equalTo(Permission.PUSH.toString().toLowerCase())); + + } + + /** + * Test create team with repo role. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetMembership() throws IOException { - GHOrganization org = gitHub.getOrganization("hub4j-test-org"); + public void testCreateTeamWithRepoRole() throws IOException { + String REPO_NAME = "github-api"; - GHMembership membership = org.getMembership("fv316"); + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHRepository repo = org.getRepository(REPO_NAME); - assertThat(membership, notNullValue()); - assertThat(membership.getRole(), equalTo(GHMembership.Role.ADMIN)); - assertThat(membership.getState(), equalTo(GHMembership.State.ACTIVE)); - assertThat(membership.getUser().getLogin(), equalTo("fv316")); - assertThat(membership.getOrganization().login, equalTo("hub4j-test-org")); + // Create team with access to repository. Check access was granted. + GHTeam team = org.createTeam(TEAM_NAME_CREATE).create(); + + RepositoryRole role = RepositoryRole.from(Permission.TRIAGE); + team.add(repo, role); + + // 'getPermission' does not return triage even though the UI shows that value + // assertThat( + // repo.getTeams() + // .stream() + // .filter(t -> TEAM_NAME_CREATE.equals(t.getName())) + // .findFirst() + // .get() + // .getPermission(), + // equalTo(role.toString())); } /** - * Test invite user. + * Test create team. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testInviteUser() throws IOException { + public void testCreateTeam() throws IOException { + String REPO_NAME = "github-api"; + String DEFAULT_PERMISSION = Permission.PULL.toString().toLowerCase(); + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHUser user = gitHub.getUser("martinvanzijl2"); + GHRepository repo = org.getRepository(REPO_NAME); - // First remove the user - if (org.hasMember(user)) { - org.remove(user); - } + // Create team with no permission field. Verify that default permission is pull + GHTeam team = org.createTeam(TEAM_NAME_CREATE).repositories(repo.getFullName()).create(); + assertThat(team.getRepositories().containsKey(REPO_NAME), is(true)); + assertThat(team.getPermission(), equalTo(DEFAULT_PERMISSION)); + } - // Then invite the user again - org.add(user, GHOrganization.Role.MEMBER); + /** + * Test create visible team. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testCreateVisibleTeam() throws IOException { + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - // Now the user has to accept the invitation - // Can this be automated? - // user.acceptInvitationTo(org); // ? + GHTeam team = org.createTeam(TEAM_NAME_CREATE).privacy(GHTeam.Privacy.CLOSED).create(); + assertThat(team.getPrivacy(), equalTo(GHTeam.Privacy.CLOSED)); + } - // Check the invitation has worked. - // assertTrue(org.hasMember(user)); + /** + * Test create all args team. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testCreateAllArgsTeam() throws IOException { + String REPO_NAME = "github-api"; + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + + GHTeam team = org.createTeam(TEAM_NAME_CREATE) + .description("Team description") + .maintainers("bitwiseman") + .repositories(REPO_NAME) + .privacy(GHTeam.Privacy.CLOSED) + .parentTeamId(3617900) + .create(); + assertThat(team.getDescription(), equalTo("Team description")); + assertThat(team.getPrivacy(), equalTo(GHTeam.Privacy.CLOSED)); } /** - * Test list external groups without pagination for non enterprise managed organization. + * Test are organization projects enabled. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testListExternalGroupsNotEnterpriseManagedOrganization() throws IOException { + public void testAreOrganizationProjectsEnabled() throws IOException { + // Arrange GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - final GHNotExternallyManagedEnterpriseException failure = assertThrows( - GHNotExternallyManagedEnterpriseException.class, - () -> org.listExternalGroups().toList()); + // Act + boolean result = org.areOrganizationProjectsEnabled(); - assertThat(failure.getMessage(), equalTo("Could not retrieve organization external groups")); + // Assert + assertThat(result, is(true)); + } - final GHError error = failure.getError(); + /** + * Test enable organization projects. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testEnableOrganizationProjects() throws IOException { + // Arrange + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - assertThat(error, notNullValue()); - assertThat(error.getMessage(), - equalTo(EnterpriseManagedSupport.NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR)); - assertThat(error.getDocumentationUrl(), notNullValue()); + // Act + org.enableOrganizationProjects(false); + + // Assert + assertThat(org.areOrganizationProjectsEnabled(), is(false)); } /** - * Test list external groups with name filtering. + * Test list external groups without pagination. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testListExternalGroupsWithFilter() throws IOException { + public void testListExternalGroupsWithoutPagination() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - List groups = org.listExternalGroups("acme").toList(); + List groups = org.listExternalGroups().toList(); assertThat(groups, notNullValue()); // In case more are added in the future @@ -559,6 +641,9 @@ public void testListExternalGroupsWithFilter() throws IOException { "467433:acme-technical-leads")); groups.forEach(group -> assertThat(group, isExternalGroupSummary())); + + // We are doing one request to get the organization and one to get the external groups + assertThat(mockGitHub.getRequestCount(), greaterThanOrEqualTo(2)); } /** @@ -589,16 +674,16 @@ public void testListExternalGroupsWithPagination() throws IOException { } /** - * Test list external groups without pagination. + * Test list external groups with name filtering. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testListExternalGroupsWithoutPagination() throws IOException { + public void testListExternalGroupsWithFilter() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - List groups = org.listExternalGroups().toList(); + List groups = org.listExternalGroups("acme").toList(); assertThat(groups, notNullValue()); // In case more are added in the future @@ -610,158 +695,73 @@ public void testListExternalGroupsWithoutPagination() throws IOException { "467433:acme-technical-leads")); groups.forEach(group -> assertThat(group, isExternalGroupSummary())); - - // We are doing one request to get the organization and one to get the external groups - assertThat(mockGitHub.getRequestCount(), greaterThanOrEqualTo(2)); } /** - * Test list members with filter. + * Test list external groups without pagination for non enterprise managed organization. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testListMembersWithFilter() throws IOException { + public void testListExternalGroupsNotEnterpriseManagedOrganization() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - List admins = org.listMembersWithFilter("all").toList(); - - assertThat(admins, notNullValue()); - // In case more are added in the future - assertThat(admins.size(), greaterThanOrEqualTo(12)); - assertThat(admins.stream().map(GHUser::getLogin).collect(Collectors.toList()), - hasItems("alexanderrtaylor", - "asthinasthi", - "bitwiseman", - "farmdawgnation", - "halkeye", - "jberglund-BSFT", - "kohsuke", - "kohsuke2", - "martinvanzijl", - "PauloMigAlmeida", - "Sage-Pierce", - "timja")); - } + final GHNotExternallyManagedEnterpriseException failure = assertThrows( + GHNotExternallyManagedEnterpriseException.class, + () -> org.listExternalGroups().toList()); - /** - * Test list members with role. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testListMembersWithRole() throws IOException { - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + assertThat(failure.getMessage(), equalTo("Could not retrieve organization external groups")); - List admins = org.listMembersWithRole("admin").toList(); + final GHError error = failure.getError(); - assertThat(admins, notNullValue()); - // In case more are added in the future - assertThat(admins.size(), greaterThanOrEqualTo(12)); - assertThat(admins.stream().map(GHUser::getLogin).collect(Collectors.toList()), - hasItems("alexanderrtaylor", - "asthinasthi", - "bitwiseman", - "farmdawgnation", - "halkeye", - "jberglund-BSFT", - "kohsuke", - "kohsuke2", - "martinvanzijl", - "PauloMigAlmeida", - "Sage-Pierce", - "timja")); + assertThat(error, notNullValue()); + assertThat(error.getMessage(), + equalTo(EnterpriseManagedSupport.NOT_PART_OF_EXTERNALLY_MANAGED_ENTERPRISE_ERROR)); + assertThat(error.getDocumentationUrl(), notNullValue()); } /** - * Test list outside collaborators. + * Test get external group * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testListOutsideCollaborators() throws IOException { + public void testGetExternalGroup() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - List admins = org.listOutsideCollaborators().toList(); + GHExternalGroup group = org.getExternalGroup(467431L); - assertThat(admins, notNullValue()); - // In case more are added in the future - assertThat(admins.size(), greaterThanOrEqualTo(12)); - assertThat(admins.stream().map(GHUser::getLogin).collect(Collectors.toList()), - hasItems("alexanderrtaylor", - "asthinasthi", - "bitwiseman", - "farmdawgnation", - "halkeye", - "jberglund-BSFT", - "kohsuke", - "kohsuke2", - "martinvanzijl", - "PauloMigAlmeida", - "Sage-Pierce", - "timja")); - } + assertThat(group, not(isExternalGroupSummary())); - /** - * Test list outside collaborators with filter. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testListOutsideCollaboratorsWithFilter() throws IOException { - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + assertThat(group.getId(), equalTo(467431L)); + assertThat(group.getName(), equalTo("acme-developers")); + assertThat(group.getUpdatedAt(), notNullValue()); - List admins = org.listOutsideCollaboratorsWithFilter("all").toList(); + assertThat(group.getMembers(), notNullValue()); + assertThat(membersSummary(group), + hasItems("158311279:john-doe_acme:John Doe:john.doe@acme.corp", + "166731041:jane-doe_acme:Jane Doe:jane.doe@acme.corp")); - assertThat(admins, notNullValue()); - // In case more are added in the future - assertThat(admins.size(), greaterThanOrEqualTo(12)); - assertThat(admins.stream().map(GHUser::getLogin).collect(Collectors.toList()), - hasItems("alexanderrtaylor", - "asthinasthi", - "bitwiseman", - "farmdawgnation", - "halkeye", - "jberglund-BSFT", - "kohsuke", - "kohsuke2", - "martinvanzijl", - "PauloMigAlmeida", - "Sage-Pierce", - "timja")); + assertThat(group.getTeams(), notNullValue()); + assertThat(teamSummary(group), hasItems("9891173:ACME-DEVELOPERS")); } /** - * Test list security managers. + * Test get external group for not enterprise managed organization * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testListSecurityManagers() throws IOException { + public void testGetExternalGroupNotEnterpriseManagedOrganization() throws IOException { GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - List securityManagers = org.listSecurityManagers().toList(); - - assertThat(securityManagers, notNullValue()); - // In case more are added in the future - assertThat(securityManagers.size(), greaterThanOrEqualTo(1)); - assertThat(securityManagers.stream().map(GHTeam::getName).collect(Collectors.toList()), - hasItems("security team")); - } + final GHIOException failure = assertThrows(GHNotExternallyManagedEnterpriseException.class, + () -> org.getExternalGroup(12345)); - /** - * Enable response templating to allow support validating pagination of external groups - * - * @return the updated WireMock options - */ - @Override - protected WireMockConfiguration getWireMockOptions() { - return super.getWireMockOptions().extensions(templating.newResponseTransformer()); + assertThat(failure.getMessage(), equalTo("Could not retrieve organization external group")); } } diff --git a/src/test/java/org/kohsuke/github/GHPersonTest.java b/src/test/java/org/kohsuke/github/GHPersonTest.java index 46fb05dd66..199885c01c 100644 --- a/src/test/java/org/kohsuke/github/GHPersonTest.java +++ b/src/test/java/org/kohsuke/github/GHPersonTest.java @@ -48,10 +48,6 @@ public void testFieldsForUser() throws Exception { assertThat(user.isSiteAdmin(), notNullValue()); } - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); - } - /** * Gets the repository. * @@ -62,4 +58,8 @@ private GHRepository getRepository(GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } } diff --git a/src/test/java/org/kohsuke/github/GHProjectCardTest.java b/src/test/java/org/kohsuke/github/GHProjectCardTest.java index 093bb56139..f3494b8a63 100644 --- a/src/test/java/org/kohsuke/github/GHProjectCardTest.java +++ b/src/test/java/org/kohsuke/github/GHProjectCardTest.java @@ -17,55 +17,16 @@ */ public class GHProjectCardTest extends AbstractGitHubWireMockTest { - private GHProjectCard card; - - private GHProjectColumn column; - private GHOrganization org; - private GHProject project; /** * Create default GHProjectCardTest instance */ public GHProjectCardTest() { } - /** - * After. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @After - public void after() throws IOException { - if (mockGitHub.isUseProxy()) { - if (card != null) { - card = getNonRecordingGitHub().getProjectCard(card.getId()); - try { - card.delete(); - card = null; - } catch (FileNotFoundException e) { - card = null; - } - } - if (column != null) { - column = getNonRecordingGitHub().getProjectColumn(column.getId()); - try { - column.delete(); - column = null; - } catch (FileNotFoundException e) { - column = null; - } - } - if (project != null) { - project = getNonRecordingGitHub().getProject(project.getId()); - try { - project.delete(); - project = null; - } catch (FileNotFoundException e) { - project = null; - } - } - } - } + private GHOrganization org; + private GHProject project; + private GHProjectColumn column; + private GHProjectCard card; /** * Sets the up. @@ -81,6 +42,29 @@ public void setUp() throws Exception { card = column.createCard("This is a card"); } + /** + * Test created card. + */ + @Test + public void testCreatedCard() { + assertThat(card.getNote(), equalTo("This is a card")); + assertThat(card.isArchived(), is(false)); + } + + /** + * Test edit card note. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testEditCardNote() throws IOException { + card.setNote("New note"); + card = gitHub.getProjectCard(card.getId()); + assertThat(card.getNote(), equalTo("New note")); + assertThat(card.isArchived(), is(false)); + } + /** * Test archive card. * @@ -107,14 +91,9 @@ public void testCreateCardFromIssue() throws IOException { try { GHIssue issue = repo.createIssue("new-issue").body("With body").create(); GHProjectCard card = column.createCard(issue); - assertThat(column.getProjectUrl(), equalTo(card.getProjectUrl())); - assertThat(card.getContentUrl(), equalTo(issue.getUrl())); assertThat(card.getContent().getUrl(), equalTo(issue.getUrl())); assertThat(card.getContent().getRepository().getUrl(), equalTo(repo.getUrl())); - assertThat(card.getProjectUrl().toString(), endsWith("/projects/13495086")); - assertThat(card.getColumnUrl().toString(), endsWith("/projects/columns/16361848")); - } finally { repo.delete(); } @@ -152,15 +131,6 @@ public void testCreateCardFromPR() throws IOException { } } - /** - * Test created card. - */ - @Test - public void testCreatedCard() { - assertThat(card.getNote(), equalTo("This is a card")); - assertThat(card.isArchived(), is(false)); - } - /** * Test delete card. * @@ -179,16 +149,41 @@ public void testDeleteCard() throws IOException { } /** - * Test edit card note. + * After. * * @throws IOException * Signals that an I/O exception has occurred. */ - @Test - public void testEditCardNote() throws IOException { - card.setNote("New note"); - card = gitHub.getProjectCard(card.getId()); - assertThat(card.getNote(), equalTo("New note")); - assertThat(card.isArchived(), is(false)); + @After + public void after() throws IOException { + if (mockGitHub.isUseProxy()) { + if (card != null) { + card = getNonRecordingGitHub().getProjectCard(card.getId()); + try { + card.delete(); + card = null; + } catch (FileNotFoundException e) { + card = null; + } + } + if (column != null) { + column = getNonRecordingGitHub().getProjectColumn(column.getId()); + try { + column.delete(); + column = null; + } catch (FileNotFoundException e) { + column = null; + } + } + if (project != null) { + project = getNonRecordingGitHub().getProject(project.getId()); + try { + project.delete(); + project = null; + } catch (FileNotFoundException e) { + project = null; + } + } + } } } diff --git a/src/test/java/org/kohsuke/github/GHProjectColumnTest.java b/src/test/java/org/kohsuke/github/GHProjectColumnTest.java index b858b4b208..ec09a4e3a2 100644 --- a/src/test/java/org/kohsuke/github/GHProjectColumnTest.java +++ b/src/test/java/org/kohsuke/github/GHProjectColumnTest.java @@ -18,44 +18,14 @@ */ public class GHProjectColumnTest extends AbstractGitHubWireMockTest { - private GHProjectColumn column; - - private GHProject project; /** * Create default GHProjectColumnTest instance */ public GHProjectColumnTest() { } - /** - * After. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @After - public void after() throws IOException { - if (mockGitHub.isUseProxy()) { - if (column != null) { - column = getNonRecordingGitHub().getProjectColumn(column.getId()); - try { - column.delete(); - column = null; - } catch (FileNotFoundException e) { - column = null; - } - } - if (project != null) { - project = getNonRecordingGitHub().getProject(project.getId()); - try { - project.delete(); - project = null; - } catch (FileNotFoundException e) { - project = null; - } - } - } - } + private GHProject project; + private GHProjectColumn column; /** * Sets the up. @@ -77,6 +47,19 @@ public void testCreatedColumn() { assertThat(column.getName(), equalTo("column-one")); } + /** + * Test edit column name. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testEditColumnName() throws IOException { + column.setName("new-name"); + column = gitHub.getProjectColumn(column.getId()); + assertThat(column.getName(), equalTo("new-name")); + } + /** * Test delete column. * @@ -95,15 +78,32 @@ public void testDeleteColumn() throws IOException { } /** - * Test edit column name. + * After. * * @throws IOException * Signals that an I/O exception has occurred. */ - @Test - public void testEditColumnName() throws IOException { - column.setName("new-name"); - column = gitHub.getProjectColumn(column.getId()); - assertThat(column.getName(), equalTo("new-name")); + @After + public void after() throws IOException { + if (mockGitHub.isUseProxy()) { + if (column != null) { + column = getNonRecordingGitHub().getProjectColumn(column.getId()); + try { + column.delete(); + column = null; + } catch (FileNotFoundException e) { + column = null; + } + } + if (project != null) { + project = getNonRecordingGitHub().getProject(project.getId()); + try { + project.delete(); + project = null; + } catch (FileNotFoundException e) { + project = null; + } + } + } } } diff --git a/src/test/java/org/kohsuke/github/GHProjectTest.java b/src/test/java/org/kohsuke/github/GHProjectTest.java index 81fce58f89..45f893e302 100644 --- a/src/test/java/org/kohsuke/github/GHProjectTest.java +++ b/src/test/java/org/kohsuke/github/GHProjectTest.java @@ -17,34 +17,13 @@ */ public class GHProjectTest extends AbstractGitHubWireMockTest { - private GHProject project; - /** * Create default GHProjectTest instance */ public GHProjectTest() { } - /** - * After. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @After - public void after() throws IOException { - if (mockGitHub.isUseProxy()) { - if (project != null) { - project = getNonRecordingGitHub().getProject(project.getId()); - try { - project.delete(); - project = null; - } catch (FileNotFoundException e) { - project = null; - } - } - } - } + private GHProject project; /** * Sets the up. @@ -59,34 +38,33 @@ public void setUp() throws Exception { /** * Test created project. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testCreatedProject() { + public void testCreatedProject() throws IOException { assertThat(project, notNullValue()); assertThat(project.getName(), equalTo("test-project")); assertThat(project.getBody(), equalTo("This is a test project")); assertThat(project.getState(), equalTo(GHProject.ProjectState.OPEN)); assertThat(project.getHtmlUrl().toString(), containsString("/orgs/hub4j-test-org/projects/")); assertThat(project.getUrl().toString(), containsString("/projects/")); - assertThat(project.getOwnerUrl().toString(), endsWith("/orgs/hub4j-test-org")); - } /** - * Test delete project. + * Test edit project name. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testDeleteProject() throws IOException { - project.delete(); - try { - project = gitHub.getProject(project.getId()); - assertThat(project, nullValue()); - } catch (FileNotFoundException e) { - project = null; - } + public void testEditProjectName() throws IOException { + project.setName("new-name"); + project = gitHub.getProject(project.getId()); + assertThat(project.getName(), equalTo("new-name")); + assertThat(project.getBody(), equalTo("This is a test project")); + assertThat(project.getState(), equalTo(GHProject.ProjectState.OPEN)); } /** @@ -105,32 +83,55 @@ public void testEditProjectBody() throws IOException { } /** - * Test edit project name. + * Test edit project state. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testEditProjectName() throws IOException { - project.setName("new-name"); + public void testEditProjectState() throws IOException { + project.setState(GHProject.ProjectState.CLOSED); project = gitHub.getProject(project.getId()); - assertThat(project.getName(), equalTo("new-name")); + assertThat(project.getName(), equalTo("test-project")); assertThat(project.getBody(), equalTo("This is a test project")); - assertThat(project.getState(), equalTo(GHProject.ProjectState.OPEN)); + assertThat(project.getState(), equalTo(GHProject.ProjectState.CLOSED)); } /** - * Test edit project state. + * Test delete project. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testEditProjectState() throws IOException { - project.setState(GHProject.ProjectState.CLOSED); - project = gitHub.getProject(project.getId()); - assertThat(project.getName(), equalTo("test-project")); - assertThat(project.getBody(), equalTo("This is a test project")); - assertThat(project.getState(), equalTo(GHProject.ProjectState.CLOSED)); + public void testDeleteProject() throws IOException { + project.delete(); + try { + project = gitHub.getProject(project.getId()); + assertThat(project, nullValue()); + } catch (FileNotFoundException e) { + project = null; + } + } + + /** + * After. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @After + public void after() throws IOException { + if (mockGitHub.isUseProxy()) { + if (project != null) { + project = getNonRecordingGitHub().getProject(project.getId()); + try { + project.delete(); + project = null; + } catch (FileNotFoundException e) { + project = null; + } + } + } } } diff --git a/src/test/java/org/kohsuke/github/GHPublicKeyTest.java b/src/test/java/org/kohsuke/github/GHPublicKeyTest.java index 023a506e40..b4f4a07b8c 100644 --- a/src/test/java/org/kohsuke/github/GHPublicKeyTest.java +++ b/src/test/java/org/kohsuke/github/GHPublicKeyTest.java @@ -9,15 +9,15 @@ */ public class GHPublicKeyTest extends AbstractGitHubWireMockTest { - private static final String TMP_KEY_NAME = "Temporary user key"; - - private static final String WIREMOCK_SSH_PUBLIC_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDepW2/BSVFM2AfuGGsvi+vjQzC0EBD3R+/7PNEvP0/nvTWxiC/tthfvvCJR6TKrsprCir5tiJFm73gX+K18W0RKYpkyg8H6d1eZu3q/JOiGvoDPeN8Oe9hOGeeexw1WOiz7ESPHzZYXI981evzHAzxxn8zibr2EryopVNsXyoenw=="; /** * Create default GHPublicKeyTest instance */ public GHPublicKeyTest() { } + private static final String TMP_KEY_NAME = "Temporary user key"; + private static final String WIREMOCK_SSH_PUBLIC_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDepW2/BSVFM2AfuGGsvi+vjQzC0EBD3R+/7PNEvP0/nvTWxiC/tthfvvCJR6TKrsprCir5tiJFm73gX+K18W0RKYpkyg8H6d1eZu3q/JOiGvoDPeN8Oe9hOGeeexw1WOiz7ESPHzZYXI981evzHAzxxn8zibr2EryopVNsXyoenw=="; + /** * Test adding a public key to the user * diff --git a/src/test/java/org/kohsuke/github/GHPullRequestMockTest.java b/src/test/java/org/kohsuke/github/GHPullRequestMockTest.java index b84c905546..45dd9af9f5 100644 --- a/src/test/java/org/kohsuke/github/GHPullRequestMockTest.java +++ b/src/test/java/org/kohsuke/github/GHPullRequestMockTest.java @@ -33,4 +33,5 @@ public void shouldMockGHPullRequest() throws IOException { assertThat("Mock should return true", pullRequest.isDraft()); } + } diff --git a/src/test/java/org/kohsuke/github/GHPullRequestTest.java b/src/test/java/org/kohsuke/github/GHPullRequestTest.java index 8fec076e08..aaaa612ea5 100644 --- a/src/test/java/org/kohsuke/github/GHPullRequestTest.java +++ b/src/test/java/org/kohsuke/github/GHPullRequestTest.java @@ -6,9 +6,10 @@ import org.kohsuke.github.GHPullRequest.AutoMerge; import java.io.IOException; -import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Optional; @@ -16,7 +17,6 @@ import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasProperty; import static org.hamcrest.Matchers.hasSize; @@ -25,8 +25,6 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -import static org.kohsuke.github.GHPullRequestReviewComment.Side.LEFT; -import static org.kohsuke.github.GHPullRequestReviewComment.Side.RIGHT; // TODO: Auto-generated Javadoc /** @@ -42,118 +40,6 @@ public class GHPullRequestTest extends AbstractGitHubWireMockTest { public GHPullRequestTest() { } - /** - * Adds the labels. - * - * @throws Exception - * the exception - */ - @Test - // Requires push access to the test repo to pass - public void addLabels() throws Exception { - GHPullRequest p = getRepository().createPullRequest("addLabels", "test/stable", "main", "## test"); - String addedLabel1 = "addLabels_label_name_1"; - String addedLabel2 = "addLabels_label_name_2"; - String addedLabel3 = "addLabels_label_name_3"; - - List resultingLabels = p.addLabels(addedLabel1); - assertThat(resultingLabels.size(), equalTo(1)); - GHLabel ghLabel = resultingLabels.get(0); - assertThat(ghLabel.getName(), equalTo(addedLabel1)); - - int requestCount = mockGitHub.getRequestCount(); - resultingLabels = p.addLabels(addedLabel2, addedLabel3); - // multiple labels can be added with one api call - assertThat(mockGitHub.getRequestCount(), equalTo(requestCount + 1)); - - assertThat(resultingLabels.size(), equalTo(3)); - assertThat(resultingLabels, - containsInAnyOrder(hasProperty("name", equalTo(addedLabel1)), - hasProperty("name", equalTo(addedLabel2)), - hasProperty("name", equalTo(addedLabel3)))); - - // Adding a label which is already present does not throw an error - resultingLabels = p.addLabels(ghLabel); - assertThat(resultingLabels.size(), equalTo(3)); - } - - /** - * Adds the labels concurrency issue. - * - * @throws Exception - * the exception - */ - @Test - // Requires push access to the test repo to pass - public void addLabelsConcurrencyIssue() throws Exception { - String addedLabel1 = "addLabelsConcurrencyIssue_label_name_1"; - String addedLabel2 = "addLabelsConcurrencyIssue_label_name_2"; - - GHPullRequest p1 = getRepository() - .createPullRequest("addLabelsConcurrencyIssue", "test/stable", "main", "## test"); - p1.getLabels(); - - GHPullRequest p2 = getRepository().getPullRequest(p1.getNumber()); - p2.addLabels(addedLabel2); - - Collection labels = p1.addLabels(addedLabel1); - - assertThat(labels.size(), equalTo(2)); - assertThat(labels, - containsInAnyOrder(hasProperty("name", equalTo(addedLabel1)), - hasProperty("name", equalTo(addedLabel2)))); - } - - /** - * Check non existent author. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void checkNonExistentAuthor() throws IOException { - // PR id is based on https://github.com/sahansera/TestRepo/pull/2 - final GHPullRequest pullRequest = getRepository().getPullRequest(2); - - assertThat(pullRequest.getUser(), is(notNullValue())); - assertThat(pullRequest.getUser().login, is("ghost")); - } - - /** - * Check non existent reviewer. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void checkNonExistentReviewer() throws IOException { - // PR id is based on https://github.com/sahansera/TestRepo/pull/1 - final GHPullRequest pullRequest = getRepository().getPullRequest(1); - final Optional review = pullRequest.listReviews().toList().stream().findFirst(); - final GHUser reviewer = review.get().getUser(); - - assertThat(pullRequest.getRequestedReviewers(), is(empty())); - assertThat(review, notNullValue()); - assertThat(reviewer, is(nullValue())); - } - - /** - * Check pull request reviewer. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void checkPullRequestReviewer() throws IOException { - // PR id is based on https://github.com/sahansera/TestRepo/pull/6 - final GHPullRequest pullRequest = getRepository().getPullRequest(6); - final Optional review = pullRequest.listReviews().toList().stream().findFirst(); - final GHUser reviewer = review.get().getUser(); - - assertThat(review, notNullValue()); - assertThat(reviewer, notNullValue()); - } - /** * Clean up. * @@ -177,52 +63,27 @@ public void cleanUp() throws Exception { } /** - * Close pull request. + * Creates the pull request. * * @throws Exception * the exception */ @Test - public void closePullRequest() throws Exception { - String name = "closePullRequest"; - GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); - // System.out.println(p.getUrl()); + public void createPullRequest() throws Exception { + String name = "createPullRequest"; + GHRepository repo = getRepository(); + GHPullRequest p = repo.createPullRequest(name, "test/stable", "main", "## test"); assertThat(p.getTitle(), equalTo(name)); - assertThat(getRepository().getPullRequest(p.getNumber()).getState(), equalTo(GHIssueState.OPEN)); - p.close(); - assertThat(getRepository().getPullRequest(p.getNumber()).getState(), equalTo(GHIssueState.CLOSED)); - } - - /** - * Comments objects in pull request review builder. - */ - @Test - public void commentsInPullRequestReviewBuilder() { - GHPullRequestReviewBuilder.DraftReviewComment draftReviewComment = new GHPullRequestReviewBuilder.DraftReviewComment( - "comment", - "path/to/file.txt", - 1); - assertThat(draftReviewComment.getBody(), equalTo("comment")); - assertThat(draftReviewComment.getPath(), equalTo("path/to/file.txt")); - assertThat(draftReviewComment.getPosition(), equalTo(1)); - - GHPullRequestReviewBuilder.SingleLineDraftReviewComment singleLineDraftReviewComment = new GHPullRequestReviewBuilder.SingleLineDraftReviewComment( - "comment", - "path/to/file.txt", - 2); - assertThat(singleLineDraftReviewComment.getBody(), equalTo("comment")); - assertThat(singleLineDraftReviewComment.getPath(), equalTo("path/to/file.txt")); - assertThat(singleLineDraftReviewComment.getLine(), equalTo(2)); + assertThat(p.canMaintainerModify(), is(false)); + assertThat(p.isDraft(), is(false)); - GHPullRequestReviewBuilder.MultilineDraftReviewComment multilineDraftReviewComment = new GHPullRequestReviewBuilder.MultilineDraftReviewComment( - "comment", - "path/to/file.txt", - 1, - 2); - assertThat(multilineDraftReviewComment.getBody(), equalTo("comment")); - assertThat(multilineDraftReviewComment.getPath(), equalTo("path/to/file.txt")); - assertThat(multilineDraftReviewComment.getStartLine(), equalTo(1)); - assertThat(multilineDraftReviewComment.getLine(), equalTo(2)); + // Check auto merge status of the pull request + final AutoMerge autoMerge = p.getAutoMerge(); + assertThat(autoMerge, is(notNullValue())); + assertThat(autoMerge.getCommitMessage(), equalTo("This is a auto merged squash commit message")); + assertThat(autoMerge.getCommitTitle(), equalTo("This is a auto merged squash commit")); + assertThat(autoMerge.getMergeMethod(), equalTo(GHPullRequest.MergeMethod.SQUASH)); + assertThat(autoMerge.getEnabledBy(), is(notNullValue())); } /** @@ -255,86 +116,86 @@ public void createDraftPullRequest() throws Exception { } /** - * Creates the pull request. + * Pull request comment. * * @throws Exception * the exception */ @Test - public void createPullRequest() throws Exception { - String name = "createPullRequest"; - GHRepository repo = getRepository(); - GHPullRequest p = repo.createPullRequest(name, "test/stable", "main", "## test"); - assertThat(p.getTitle(), equalTo(name)); - assertThat(p.canMaintainerModify(), is(false)); - assertThat(p.isDraft(), is(false)); + public void pullRequestComment() throws Exception { + String name = "createPullRequestComment"; + GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); - // Check auto merge status of the pull request - final AutoMerge autoMerge = p.getAutoMerge(); - assertThat(autoMerge, is(notNullValue())); - assertThat(autoMerge.getCommitMessage(), equalTo("This is a auto merged squash commit message")); - assertThat(autoMerge.getCommitTitle(), equalTo("This is a auto merged squash commit")); - assertThat(autoMerge.getMergeMethod(), equalTo(GHPullRequest.MergeMethod.SQUASH)); - assertThat(autoMerge.getEnabledBy(), is(notNullValue())); - } + List comments; + comments = p.listComments().toList(); + assertThat(comments, hasSize(0)); + comments = p.queryComments().list().toList(); + assertThat(comments, hasSize(0)); - /** - * - * Test enabling auto merge for pull request - * - * @throws IOException - * the Exception - */ - @Test - public void enablePullRequestAutoMerge() throws IOException { - String authorEmail = "sa20207@naver.com"; - String clientMutationId = "github-api"; - String commitBody = "This is commit body."; - String commitTitle = "This is commit title."; - String expectedCommitHeadOid = "4888b44d7204dd05680e90159af839c8b1194b6d"; - - GHPullRequest pullRequest = gitHub.getRepository("seate/for-test").getPullRequest(9); - - pullRequest.enablePullRequestAutoMerge(authorEmail, - clientMutationId, - commitBody, - commitTitle, - expectedCommitHeadOid, - GHPullRequest.MergeMethod.MERGE); - - AutoMerge autoMerge = pullRequest.getAutoMerge(); - assertThat(autoMerge.getEnabledBy().getEmail(), is(authorEmail)); - assertThat(autoMerge.getCommitMessage(), is(commitBody)); - assertThat(autoMerge.getCommitTitle(), is(commitTitle)); - assertThat(autoMerge.getMergeMethod(), is(GHPullRequest.MergeMethod.MERGE)); - } + GHIssueComment firstComment = p.comment("First comment"); + Date firstCommentCreatedAt = firstComment.getCreatedAt(); + Date firstCommentCreatedAtPlus1Second = Date + .from(firstComment.getCreatedAt().toInstant().plus(1, ChronoUnit.SECONDS)); - /** - * Test enabling auto merge for pull request with no verified email throws GraphQL exception - * - * @throws IOException - * the io exception - */ - @Test - public void enablePullRequestAutoMergeFailure() throws IOException { - String authorEmail = "failureEmail@gmail.com"; - String clientMutationId = "github-api"; - String commitBody = "This is commit body."; - String commitTitle = "This is commit title."; - String expectedCommitHeadOid = "4888b44d7204dd05680e90159af839c8b1194b6d"; + comments = p.listComments().toList(); + assertThat(comments, hasSize(1)); + assertThat(comments, contains(hasProperty("body", equalTo("First comment")))); + comments = p.queryComments().list().toList(); + assertThat(comments, hasSize(1)); + assertThat(comments, contains(hasProperty("body", equalTo("First comment")))); + + // Test "since" + comments = p.queryComments().since(firstCommentCreatedAt).list().toList(); + assertThat(comments, hasSize(1)); + assertThat(comments, contains(hasProperty("body", equalTo("First comment")))); + comments = p.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList(); + assertThat(comments, hasSize(0)); + + // "since" is only precise up to the second, + // so if we want to differentiate comments, we need to be completely sure they're created + // at least 1 second from each other. + // Waiting 2 seconds to avoid edge cases. + Thread.sleep(2000); - GHPullRequest pullRequest = gitHub.getRepository("seate/for-test").getPullRequest(9); + GHIssueComment secondComment = p.comment("Second comment"); + Date secondCommentCreatedAt = secondComment.getCreatedAt(); + Date secondCommentCreatedAtPlus1Second = Date + .from(secondComment.getCreatedAt().toInstant().plus(1, ChronoUnit.SECONDS)); + assertThat( + "There's an error in the setup of this test; please fix it." + + " The second comment should be created at least one second after the first one.", + firstCommentCreatedAtPlus1Second.getTime() <= secondCommentCreatedAt.getTime()); - try { - pullRequest.enablePullRequestAutoMerge(authorEmail, - clientMutationId, - commitBody, - commitTitle, - expectedCommitHeadOid, - null); - } catch (IOException e) { - assertThat(e.getMessage(), containsString("does not have a verified email")); - } + comments = p.listComments().toList(); + assertThat(comments, hasSize(2)); + assertThat(comments, + contains(hasProperty("body", equalTo("First comment")), + hasProperty("body", equalTo("Second comment")))); + comments = p.queryComments().list().toList(); + assertThat(comments, hasSize(2)); + assertThat(comments, + contains(hasProperty("body", equalTo("First comment")), + hasProperty("body", equalTo("Second comment")))); + + // Test "since" + comments = p.queryComments().since(firstCommentCreatedAt).list().toList(); + assertThat(comments, hasSize(2)); + assertThat(comments, + contains(hasProperty("body", equalTo("First comment")), + hasProperty("body", equalTo("Second comment")))); + comments = p.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList(); + assertThat(comments, hasSize(1)); + assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); + comments = p.queryComments().since(secondCommentCreatedAt).list().toList(); + assertThat(comments, hasSize(1)); + assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); + comments = p.queryComments().since(secondCommentCreatedAtPlus1Second).list().toList(); + assertThat(comments, hasSize(0)); + + // Test "since" with timestamp instead of Date + comments = p.queryComments().since(secondCommentCreatedAt.getTime()).list().toList(); + assertThat(comments, hasSize(1)); + assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); } /** @@ -354,39 +215,8 @@ public void getListOfCommits() throws Exception { Optional firstPR = builder.list().toList().stream().findFirst(); try { - GHPullRequestCommitDetail detail = firstPR.get().listCommits().toArray()[0]; - assertThat(detail.getApiUrl().toString(), notNullValue()); - assertThat(detail.getSha(), equalTo("2d29c787b46ce61b98a1c13e05e21ebc21f49dbf")); - assertThat(detail.getCommentsUrl().toString(), - endsWith( - "/repos/hub4j-test-org/github-api/commits/2d29c787b46ce61b98a1c13e05e21ebc21f49dbf/comments")); - assertThat(detail.getUrl().toString(), - equalTo("https://github.com/hub4j-test-org/github-api/commit/2d29c787b46ce61b98a1c13e05e21ebc21f49dbf")); - - GHPullRequestCommitDetail.Commit commit = detail.getCommit(); - assertThat(commit, notNullValue()); - assertThat(commit.getAuthor().getEmail(), equalTo("bitwiseman@gmail.com")); - assertThat(commit.getCommitter().getEmail(), equalTo("bitwiseman@gmail.com")); - assertThat(commit.getMessage(), equalTo("Update README")); - assertThat(commit.getUrl().toString(), - endsWith("/repos/hub4j-test-org/github-api/git/commits/2d29c787b46ce61b98a1c13e05e21ebc21f49dbf")); - assertThat(commit.getComment_count(), equalTo(0)); - - GHPullRequestCommitDetail.Tree tree = commit.getTree(); - assertThat(tree, notNullValue()); - assertThat(tree.getSha(), equalTo("ce7a1ba95aba901cf08d9f8365410d290d6c23aa")); - assertThat(tree.getUrl().toString(), - endsWith("/repos/hub4j-test-org/github-api/git/trees/ce7a1ba95aba901cf08d9f8365410d290d6c23aa")); - - GHPullRequestCommitDetail.CommitPointer[] parents = detail.getParents(); - assertThat(parents, notNullValue()); - assertThat(parents.length, equalTo(1)); - assertThat(parents[0].getSha(), equalTo("3a09d2de4a9a1322a0ba2c3e2f54a919ca8fe353")); - assertThat(parents[0].getHtml_url().toString(), - equalTo("https://github.com/hub4j-test-org/github-api/commit/3a09d2de4a9a1322a0ba2c3e2f54a919ca8fe353")); - assertThat(parents[0].getUrl().toString(), - endsWith("/repos/hub4j-test-org/github-api/commits/3a09d2de4a9a1322a0ba2c3e2f54a919ca8fe353")); - + String val = firstPR.get().listCommits().toArray()[0].getApiUrl().toString(); + assertThat(val, notNullValue()); } catch (GHFileNotFoundException e) { if (e.getMessage().contains("/issues/")) { fail("Issued a request against the wrong path"); @@ -395,146 +225,96 @@ public void getListOfCommits() throws Exception { } /** - * Gets the user test. + * Close pull request. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void getUserTest() throws IOException { - GHPullRequest p = getRepository().createPullRequest("getUserTest", "test/stable", "main", "## test"); - GHPullRequest prSingle = getRepository().getPullRequest(p.getNumber()); - assertThat(prSingle.getUser().root(), notNullValue()); - prSingle.getMergeable(); - assertThat(prSingle.getUser().root(), notNullValue()); - - List ghPullRequests = getRepository().getPullRequests(GHIssueState.OPEN); - for (GHPullRequest pr : ghPullRequests) { - assertThat(pr.getUser().root(), notNullValue()); - pr.getMergeable(); - assertThat(pr.getUser().root(), notNullValue()); - } + public void closePullRequest() throws Exception { + String name = "closePullRequest"; + GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); + // System.out.println(p.getUrl()); + assertThat(p.getTitle(), equalTo(name)); + assertThat(getRepository().getPullRequest(p.getNumber()).getState(), equalTo(GHIssueState.OPEN)); + p.close(); + assertThat(getRepository().getPullRequest(p.getNumber()).getState(), equalTo(GHIssueState.CLOSED)); } /** - * Merge commit SHA. + * Pull request reviews. * * @throws Exception * the exception */ @Test - public void mergeCommitSHA() throws Exception { - String name = "mergeCommitSHA"; - GHRepository repo = getRepository(); - GHPullRequest p = repo.createPullRequest(name, "test/mergeable_branch", "main", "## test"); - int baseRequestCount = mockGitHub.getRequestCount(); - assertThat(p.getMergeableNoRefresh(), nullValue()); - assertThat("Used existing value", mockGitHub.getRequestCount() - baseRequestCount, equalTo(0)); - - // mergeability computation takes time, this should still be null immediately after creation - assertThat(p.getMergeable(), nullValue()); - assertThat("Asked for PR information", mockGitHub.getRequestCount() - baseRequestCount, equalTo(1)); - - for (int i = 2; i <= 10; i++) { - if (Boolean.TRUE.equals(p.getMergeable()) && p.getMergeCommitSha() != null) { - assertThat("Asked for PR information", mockGitHub.getRequestCount() - baseRequestCount, equalTo(i)); - - // make sure commit exists - GHCommit commit = repo.getCommit(p.getMergeCommitSha()); - assertThat(commit, notNullValue()); - - assertThat("Asked for PR information", mockGitHub.getRequestCount() - baseRequestCount, equalTo(i + 1)); + public void pullRequestReviews() throws Exception { + String name = "testPullRequestReviews"; + GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); - return; - } + List reviews = p.listReviews().toList(); + assertThat(reviews.size(), is(0)); - // mergeability computation takes time. give it more chance - Thread.sleep(1000); - } - // hmm? - fail(); + GHPullRequestReview draftReview = p.createReview() + .body("Some draft review") + .comment("Some niggle", "README.md", 1) + .singleLineComment("A single line comment", "README.md", 2) + .multiLineComment("A multiline comment", "README.md", 2, 3) + .create(); + assertThat(draftReview.getState(), is(GHPullRequestReviewState.PENDING)); + assertThat(draftReview.getBody(), is("Some draft review")); + assertThat(draftReview.getCommitId(), notNullValue()); + reviews = p.listReviews().toList(); + assertThat(reviews.size(), is(1)); + GHPullRequestReview review = reviews.get(0); + assertThat(review.getState(), is(GHPullRequestReviewState.PENDING)); + assertThat(review.getBody(), is("Some draft review")); + assertThat(review.getCommitId(), notNullValue()); + draftReview.submit("Some review comment", GHPullRequestReviewEvent.COMMENT); + List comments = review.listReviewComments().toList(); + assertThat(comments.size(), equalTo(3)); + GHPullRequestReviewComment comment = comments.get(0); + assertThat(comment.getBody(), equalTo("Some niggle")); + comment = comments.get(1); + assertThat(comment.getBody(), equalTo("A single line comment")); + assertThat(comment.getPosition(), equalTo(4)); + comment = comments.get(2); + assertThat(comment.getBody(), equalTo("A multiline comment")); + assertThat(comment.getPosition(), equalTo(5)); + draftReview = p.createReview().body("Some new review").comment("Some niggle", "README.md", 1).create(); + draftReview.delete(); } /** - * Pull request comment. - * - * @throws Exception - * the exception + * Comments objects in pull request review builder. */ @Test - public void pullRequestComment() throws Exception { - String name = "createPullRequestComment"; - GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); - assertThat(p.getIssueUrl().toString(), endsWith("/repos/hub4j-test-org/github-api/issues/461")); - - List comments; - comments = p.listComments().toList(); - assertThat(comments, hasSize(0)); - comments = p.queryComments().list().toList(); - assertThat(comments, hasSize(0)); - - GHIssueComment firstComment = p.comment("First comment"); - Instant firstCommentCreatedAt = firstComment.getCreatedAt(); - Instant firstCommentCreatedAtPlus1Second = firstComment.getCreatedAt().plusSeconds(1); - - comments = p.listComments().toList(); - assertThat(comments, hasSize(1)); - assertThat(comments, contains(hasProperty("body", equalTo("First comment")))); - comments = p.queryComments().list().toList(); - assertThat(comments, hasSize(1)); - assertThat(comments, contains(hasProperty("body", equalTo("First comment")))); - - // Test "since" - comments = p.queryComments().since(firstCommentCreatedAt).list().toList(); - assertThat(comments, hasSize(1)); - assertThat(comments, contains(hasProperty("body", equalTo("First comment")))); - comments = p.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList(); - assertThat(comments, hasSize(0)); - - // "since" is only precise up to the second, - // so if we want to differentiate comments, we need to be completely sure they're created - // at least 1 second from each other. - // Waiting 2 seconds to avoid edge cases. - Thread.sleep(2000); - - GHIssueComment secondComment = p.comment("Second comment"); - Instant secondCommentCreatedAt = secondComment.getCreatedAt(); - Instant secondCommentCreatedAtPlus1Second = secondComment.getCreatedAt().plusSeconds(1); - assertThat( - "There's an error in the setup of this test; please fix it." - + " The second comment should be created at least one second after the first one.", - firstCommentCreatedAtPlus1Second.isBefore(secondCommentCreatedAt)); - - comments = p.listComments().toList(); - assertThat(comments, hasSize(2)); - assertThat(comments, - contains(hasProperty("body", equalTo("First comment")), - hasProperty("body", equalTo("Second comment")))); - comments = p.queryComments().list().toList(); - assertThat(comments, hasSize(2)); - assertThat(comments, - contains(hasProperty("body", equalTo("First comment")), - hasProperty("body", equalTo("Second comment")))); + public void commentsInPullRequestReviewBuilder() { + GHPullRequestReviewBuilder.DraftReviewComment draftReviewComment = new GHPullRequestReviewBuilder.DraftReviewComment( + "comment", + "path/to/file.txt", + 1); + assertThat(draftReviewComment.getBody(), equalTo("comment")); + assertThat(draftReviewComment.getPath(), equalTo("path/to/file.txt")); + assertThat(draftReviewComment.getPosition(), equalTo(1)); - // Test "since" - comments = p.queryComments().since(firstCommentCreatedAt).list().toList(); - assertThat(comments, hasSize(2)); - assertThat(comments, - contains(hasProperty("body", equalTo("First comment")), - hasProperty("body", equalTo("Second comment")))); - comments = p.queryComments().since(firstCommentCreatedAtPlus1Second).list().toList(); - assertThat(comments, hasSize(1)); - assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); - comments = p.queryComments().since(secondCommentCreatedAt).list().toList(); - assertThat(comments, hasSize(1)); - assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); - comments = p.queryComments().since(secondCommentCreatedAtPlus1Second).list().toList(); - assertThat(comments, hasSize(0)); + GHPullRequestReviewBuilder.SingleLineDraftReviewComment singleLineDraftReviewComment = new GHPullRequestReviewBuilder.SingleLineDraftReviewComment( + "comment", + "path/to/file.txt", + 2); + assertThat(singleLineDraftReviewComment.getBody(), equalTo("comment")); + assertThat(singleLineDraftReviewComment.getPath(), equalTo("path/to/file.txt")); + assertThat(singleLineDraftReviewComment.getLine(), equalTo(2)); - // Test "since" with timestamp instead of Date - comments = p.queryComments().since(secondCommentCreatedAt.toEpochMilli()).list().toList(); - assertThat(comments, hasSize(1)); - assertThat(comments, contains(hasProperty("body", equalTo("Second comment")))); + GHPullRequestReviewBuilder.MultilineDraftReviewComment multilineDraftReviewComment = new GHPullRequestReviewBuilder.MultilineDraftReviewComment( + "comment", + "path/to/file.txt", + 1, + 2); + assertThat(multilineDraftReviewComment.getBody(), equalTo("comment")); + assertThat(multilineDraftReviewComment.getPath(), equalTo("path/to/file.txt")); + assertThat(multilineDraftReviewComment.getStartLine(), equalTo(1)); + assertThat(multilineDraftReviewComment.getLine(), equalTo(2)); } /** @@ -557,14 +337,12 @@ public void pullRequestReviewComments() throws Exception { .body("A single line review comment") .path("README.md") .line(2) - .side(RIGHT) .create(); p.createReviewComment() .commitId(p.getHead().getSha()) .body("A multiline review comment") .path("README.md") .lines(2, 3) - .sides(RIGHT, RIGHT) .create(); List comments = p.listReviewComments().toList(); assertThat(comments.size(), equalTo(3)); @@ -584,7 +362,7 @@ public void pullRequestReviewComments() throws Exception { assertThat(comment.getStartSide(), equalTo(GHPullRequestReviewComment.Side.UNKNOWN)); assertThat(comment.getLine(), equalTo(1)); assertThat(comment.getOriginalLine(), equalTo(1)); - assertThat(comment.getSide(), equalTo(LEFT)); + assertThat(comment.getSide(), equalTo(GHPullRequestReviewComment.Side.LEFT)); assertThat(comment.getPullRequestUrl(), notNullValue()); assertThat(comment.getPullRequestUrl().toString(), containsString("hub4j-test-org/github-api/pulls/")); assertThat(comment.getBodyHtml(), nullValue()); @@ -597,14 +375,11 @@ public void pullRequestReviewComments() throws Exception { comment = comments.get(1); assertThat(comment.getBody(), equalTo("A single line review comment")); assertThat(comment.getLine(), equalTo(2)); - assertThat(comment.getSide(), equalTo(RIGHT)); comment = comments.get(2); assertThat(comment.getBody(), equalTo("A multiline review comment")); assertThat(comment.getStartLine(), equalTo(2)); assertThat(comment.getLine(), equalTo(3)); - assertThat(comment.getStartSide(), equalTo(RIGHT)); - assertThat(comment.getSide(), equalTo(RIGHT)); comment.createReaction(ReactionContent.EYES); GHReaction toBeRemoved = comment.createReaction(ReactionContent.CONFUSED); @@ -668,211 +443,96 @@ public void pullRequestReviewComments() throws Exception { } /** - * Pull request reviews. + * Test pull request review requests. * * @throws Exception * the exception */ @Test - public void pullRequestReviews() throws Exception { - String name = "testPullRequestReviews"; + public void testPullRequestReviewRequests() throws Exception { + String name = "testPullRequestReviewRequests"; GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); + // System.out.println(p.getUrl()); + assertThat(p.getRequestedReviewers(), is(empty())); - List reviews = p.listReviews().toList(); - assertThat(reviews.size(), is(0)); - - GHPullRequestReview draftReview = p.createReview() - .body("Some draft review") - .comment("Some niggle", "README.md", 1) - .singleLineComment("A single line comment", "README.md", 2) - .multiLineComment("A multiline comment", "README.md", 2, 3) - .create(); - assertThat(draftReview.getState(), is(GHPullRequestReviewState.PENDING)); - assertThat(draftReview.getBody(), is("Some draft review")); - assertThat(draftReview.getCommitId(), notNullValue()); - reviews = p.listReviews().toList(); - assertThat(reviews.size(), is(1)); - GHPullRequestReview review = reviews.get(0); - assertThat(review.getState(), is(GHPullRequestReviewState.PENDING)); - assertThat(review.getBody(), is("Some draft review")); - assertThat(review.getCommitId(), notNullValue()); - draftReview.submit("Some review comment", GHPullRequestReviewEvent.COMMENT); - List comments = review.listReviewComments().toList(); - assertThat(comments.size(), equalTo(3)); - GHPullRequestReviewComment comment = comments.get(0); - assertThat(comment.getBody(), equalTo("Some niggle")); - comment = comments.get(1); - assertThat(comment.getBody(), equalTo("A single line comment")); - assertThat(comment.getPosition(), equalTo(4)); - comment = comments.get(2); - assertThat(comment.getBody(), equalTo("A multiline comment")); - assertThat(comment.getPosition(), equalTo(5)); - draftReview = p.createReview().body("Some new review").comment("Some niggle", "README.md", 1).create(); - draftReview.delete(); + GHUser kohsuke2 = gitHub.getUser("kohsuke2"); + p.requestReviewers(Collections.singletonList(kohsuke2)); + p.refresh(); + assertThat(p.getRequestedReviewers(), is(not(empty()))); } /** - * Query pull requests qualified head. + * Test pull request team review requests. * * @throws Exception * the exception */ @Test - public void queryPullRequestsQualifiedHead() throws Exception { - GHRepository repo = getRepository(); - // Create PRs from two different branches to main - repo.createPullRequest("queryPullRequestsQualifiedHead_stable", "test/stable", "main", null); - repo.createPullRequest("queryPullRequestsQualifiedHead_rc", "test/rc", "main", null); + public void testPullRequestTeamReviewRequests() throws Exception { + String name = "testPullRequestTeamReviewRequests"; + GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); + // System.out.println(p.getUrl()); + assertThat(p.getRequestedReviewers(), is(empty())); - // Query by one of the heads and make sure we only get that branch's PR back. - List prs = repo.queryPullRequests() - .state(GHIssueState.OPEN) - .head("hub4j-test-org:test/stable") - .base("main") - .list() - .toList(); - assertThat(prs, notNullValue()); - assertThat(prs.size(), equalTo(1)); - assertThat(prs.get(0).getHead().getRef(), equalTo("test/stable")); - } + GHOrganization testOrg = gitHub.getOrganization("hub4j-test-org"); + GHTeam testTeam = testOrg.getTeamBySlug("dummy-team"); - /** - * Query pull requests unqualified head. - * - * @throws Exception - * the exception - */ - @Test - public void queryPullRequestsUnqualifiedHead() throws Exception { - GHRepository repo = getRepository(); - // Create PRs from two different branches to main - repo.createPullRequest("queryPullRequestsUnqualifiedHead_stable", "test/stable", "main", null); - repo.createPullRequest("queryPullRequestsUnqualifiedHead_rc", "test/rc", "main", null); + p.requestTeamReviewers(Collections.singletonList(testTeam)); - // Query by one of the heads and make sure we only get that branch's PR back. - List prs = repo.queryPullRequests() - .state(GHIssueState.OPEN) - .head("test/stable") - .base("main") - .list() - .toList(); - assertThat(prs, notNullValue()); - assertThat(prs.size(), equalTo(1)); - assertThat(prs.get(0).getHead().getRef(), equalTo("test/stable")); + int baseRequestCount = mockGitHub.getRequestCount(); + p.refresh(); + assertThat("We should not eagerly load organizations for teams", + mockGitHub.getRequestCount() - baseRequestCount, + equalTo(1)); + assertThat(p.getRequestedTeams().size(), equalTo(1)); + assertThat("We should not eagerly load organizations for teams", + mockGitHub.getRequestCount() - baseRequestCount, + equalTo(1)); + assertThat("Org should be queried for automatically if asked for", + p.getRequestedTeams().get(0).getOrganization(), + notNullValue()); + assertThat("Request count should show lazy load occurred", + mockGitHub.getRequestCount() - baseRequestCount, + equalTo(2)); } /** - * Create/Delete reaction for pull requests. + * Merge commit SHA. * * @throws Exception * the exception */ @Test - public void reactions() throws Exception { - String name = "createPullRequest"; + public void mergeCommitSHA() throws Exception { + String name = "mergeCommitSHA"; GHRepository repo = getRepository(); - GHPullRequest p = repo.createPullRequest(name, "test/stable", "main", "## test"); - - assertThat(p.listReactions().toList(), hasSize(0)); - GHReaction reaction = p.createReaction(ReactionContent.CONFUSED); - assertThat(p.listReactions().toList(), hasSize(1)); - - p.deleteReaction(reaction); - assertThat(p.listReactions().toList(), hasSize(0)); - } - - /** - * Test refreshing a PR coming from the search results. - * - * @throws Exception - * the exception - */ - @Test - public void refreshFromSearchResults() throws Exception { - // To re-record, uncomment the Thread.sleep() calls below - snapshotNotAllowed(); - - String prName = "refreshFromSearchResults"; - GHRepository repository = getRepository(); - - repository.createPullRequest(prName, "test/stable", "main", "## test"); - - // we need to wait a bit for the pull request to be indexed by GitHub - // Thread.sleep(2000); - - GHPullRequest pullRequestFromSearchResults = repository.searchPullRequests() - .isOpen() - .titleLike(prName) - .list() - .toList() - .get(0); - - pullRequestFromSearchResults.getMergeableState(); - - // wait a bit for the mergeable state to get populated - // Thread.sleep(5000); - - assertThat("Pull request is supposed to have been refreshed and have a mergeable state", - pullRequestFromSearchResults.getMergeableState(), - equalTo("clean")); - - pullRequestFromSearchResults.close(); - } + GHPullRequest p = repo.createPullRequest(name, "test/mergeable_branch", "main", "## test"); + int baseRequestCount = mockGitHub.getRequestCount(); + assertThat(p.getMergeableNoRefresh(), nullValue()); + assertThat("Used existing value", mockGitHub.getRequestCount() - baseRequestCount, equalTo(0)); - /** - * Removes the labels. - * - * @throws Exception - * the exception - */ - @Test - // Requires push access to the test repo to pass - public void removeLabels() throws Exception { - GHPullRequest p = getRepository().createPullRequest("removeLabels", "test/stable", "main", "## test"); - String label1 = "removeLabels_label_name_1"; - String label2 = "removeLabels_label_name_2"; - String label3 = "removeLabels_label_name_3"; - p.setLabels(label1, label2, label3); + // mergeability computation takes time, this should still be null immediately after creation + assertThat(p.getMergeable(), nullValue()); + assertThat("Asked for PR information", mockGitHub.getRequestCount() - baseRequestCount, equalTo(1)); - Collection labels = getRepository().getPullRequest(p.getNumber()).getLabels(); - assertThat(labels.size(), equalTo(3)); - GHLabel ghLabel3 = labels.stream().filter(label -> label3.equals(label.getName())).findFirst().get(); + for (int i = 2; i <= 10; i++) { + if (Boolean.TRUE.equals(p.getMergeable()) && p.getMergeCommitSha() != null) { + assertThat("Asked for PR information", mockGitHub.getRequestCount() - baseRequestCount, equalTo(i)); - int requestCount = mockGitHub.getRequestCount(); - List resultingLabels = p.removeLabels(label2, label3); - // each label deleted is a separate api call - assertThat(mockGitHub.getRequestCount(), equalTo(requestCount + 2)); + // make sure commit exists + GHCommit commit = repo.getCommit(p.getMergeCommitSha()); + assertThat(commit, notNullValue()); - assertThat(resultingLabels.size(), equalTo(1)); - assertThat(resultingLabels.get(0).getName(), equalTo(label1)); + assertThat("Asked for PR information", mockGitHub.getRequestCount() - baseRequestCount, equalTo(i + 1)); - // Removing some labels that are not present does not throw - // This is consistent with earlier behavior and with addLabels() - p.removeLabels(ghLabel3); + return; + } - // Calling removeLabel() on label that is not present will throw - try { - p.removeLabel(label3); - fail("Expected GHFileNotFoundException"); - } catch (GHFileNotFoundException e) { - assertThat(e.getMessage(), containsString("Label does not exist")); + // mergeability computation takes time. give it more chance + Thread.sleep(1000); } - } - - /** - * Sets the assignee. - * - * @throws Exception - * the exception - */ - @Test - // Requires push access to the test repo to pass - public void setAssignee() throws Exception { - GHPullRequest p = getRepository().createPullRequest("setAssignee", "test/stable", "main", "## test"); - GHMyself user = gitHub.getMyself(); - p.assignTo(user); - - assertThat(getRepository().getPullRequest(p.getNumber()).getAssignee(), equalTo(user)); + // hmm? + fail(); } /** @@ -929,25 +589,74 @@ public void setBaseBranchNonExisting() throws Exception { } /** - * Sets the labels. + * Update outdated branches unexpected head. * * @throws Exception * the exception */ @Test - // Requires push access to the test repo to pass - public void setLabels() throws Exception { - GHPullRequest p = getRepository().createPullRequest("setLabels", "test/stable", "main", "## test"); - String label = "setLabels_label_name"; - p.setLabels(label); + public void updateOutdatedBranchesUnexpectedHead() throws Exception { + String prName = "testUpdateOutdatedBranches"; + String outdatedRefName = "refs/heads/outdated"; + GHRepository repository = gitHub.getOrganization("hub4j-test-org").getRepository("updateOutdatedBranches"); - Collection labels = getRepository().getPullRequest(p.getNumber()).getLabels(); - assertThat(labels.size(), equalTo(1)); - GHLabel savedLabel = labels.iterator().next(); - assertThat(savedLabel.getName(), equalTo(label)); - assertThat(savedLabel.getId(), notNullValue()); - assertThat(savedLabel.getNodeId(), notNullValue()); - assertThat(savedLabel.isDefault(), is(false)); + GHRef outdatedRef = repository.getRef(outdatedRefName); + outdatedRef.updateTo("6440189369f9f33b2366556a94dbc26f2cfdd969", true); + + GHPullRequest outdatedPullRequest = repository.createPullRequest(prName, "outdated", "main", "## test"); + + do { + Thread.sleep(5000); + outdatedPullRequest.refresh(); + } while (outdatedPullRequest.getMergeableState().equalsIgnoreCase("unknown")); + + assertThat("Pull request is supposed to be not up to date", + outdatedPullRequest.getMergeableState(), + equalTo("behind")); + + outdatedRef.updateTo("f567328eb81270487864963b7d7446953353f2b5", true); + + try { + outdatedPullRequest.updateBranch(); + } catch (HttpException e) { + assertThat(e, instanceOf(HttpException.class)); + assertThat(e.toString(), containsString("expected head sha didn’t match current head ref.")); + } + + outdatedPullRequest.close(); + } + + /** + * Update outdated branches. + * + * @throws Exception + * the exception + */ + @Test + public void updateOutdatedBranches() throws Exception { + String prName = "testUpdateOutdatedBranches"; + String outdatedRefName = "refs/heads/outdated"; + GHRepository repository = gitHub.getOrganization("hub4j-test-org").getRepository("updateOutdatedBranches"); + + repository.getRef(outdatedRefName).updateTo("6440189369f9f33b2366556a94dbc26f2cfdd969", true); + + GHPullRequest outdatedPullRequest = repository.createPullRequest(prName, "outdated", "main", "## test"); + + do { + Thread.sleep(5000); + outdatedPullRequest.refresh(); + } while (outdatedPullRequest.getMergeableState().equalsIgnoreCase("unknown")); + + assertThat("Pull request is supposed to be not up to date", + outdatedPullRequest.getMergeableState(), + equalTo("behind")); + + outdatedPullRequest.updateBranch(); + outdatedPullRequest.refresh(); + + assertThat("Pull request is supposed to be up to date", outdatedPullRequest.getMergeableState(), not("behind")); + + outdatedPullRequest.close(); } /** @@ -971,72 +680,18 @@ public void squashMerge() throws Exception { } /** - * Test pull request review requests. + * Update content squash merge. * * @throws Exception * the exception */ @Test - public void testPullRequestReviewRequests() throws Exception { - String name = "testPullRequestReviewRequests"; - GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); - // System.out.println(p.getUrl()); - assertThat(p.getRequestedReviewers(), is(empty())); - - GHUser kohsuke2 = gitHub.getUser("kohsuke2"); - p.requestReviewers(Collections.singletonList(kohsuke2)); - p.refresh(); - assertThat(p.getRequestedReviewers(), is(not(empty()))); - } + public void updateContentSquashMerge() throws Exception { + String name = "updateContentSquashMerge"; + String branchName = "test/" + name; - /** - * Test pull request team review requests. - * - * @throws Exception - * the exception - */ - @Test - public void testPullRequestTeamReviewRequests() throws Exception { - String name = "testPullRequestTeamReviewRequests"; - GHPullRequest p = getRepository().createPullRequest(name, "test/stable", "main", "## test"); - // System.out.println(p.getUrl()); - assertThat(p.getRequestedReviewers(), is(empty())); - - GHOrganization testOrg = gitHub.getOrganization("hub4j-test-org"); - GHTeam testTeam = testOrg.getTeamBySlug("dummy-team"); - - p.requestTeamReviewers(Collections.singletonList(testTeam)); - - int baseRequestCount = mockGitHub.getRequestCount(); - p.refresh(); - assertThat("We should not eagerly load organizations for teams", - mockGitHub.getRequestCount() - baseRequestCount, - equalTo(1)); - assertThat(p.getRequestedTeams().size(), equalTo(1)); - assertThat("We should not eagerly load organizations for teams", - mockGitHub.getRequestCount() - baseRequestCount, - equalTo(1)); - assertThat("Org should be queried for automatically if asked for", - p.getRequestedTeams().get(0).getOrganization(), - notNullValue()); - assertThat("Request count should show lazy load occurred", - mockGitHub.getRequestCount() - baseRequestCount, - equalTo(2)); - } - - /** - * Update content squash merge. - * - * @throws Exception - * the exception - */ - @Test - public void updateContentSquashMerge() throws Exception { - String name = "updateContentSquashMerge"; - String branchName = "test/" + name; - - GHRef mainRef = getRepository().getRef("heads/main"); - GHRef branchRef = getRepository().createRef("refs/heads/" + branchName, mainRef.getObject().getSha()); + GHRef mainRef = getRepository().getRef("heads/main"); + GHRef branchRef = getRepository().createRef("refs/heads/" + branchName, mainRef.getObject().getSha()); GHContentUpdateResponse response = getRepository().createContent() .content(name) @@ -1060,78 +715,325 @@ public void updateContentSquashMerge() throws Exception { } /** - * Update outdated branches. + * Query pull requests qualified head. * * @throws Exception * the exception */ @Test - public void updateOutdatedBranches() throws Exception { - String prName = "testUpdateOutdatedBranches"; - String outdatedRefName = "refs/heads/outdated"; - GHRepository repository = gitHub.getOrganization("hub4j-test-org").getRepository("updateOutdatedBranches"); + public void queryPullRequestsQualifiedHead() throws Exception { + GHRepository repo = getRepository(); + // Create PRs from two different branches to main + repo.createPullRequest("queryPullRequestsQualifiedHead_stable", "test/stable", "main", null); + repo.createPullRequest("queryPullRequestsQualifiedHead_rc", "test/rc", "main", null); - repository.getRef(outdatedRefName).updateTo("6440189369f9f33b2366556a94dbc26f2cfdd969", true); + // Query by one of the heads and make sure we only get that branch's PR back. + List prs = repo.queryPullRequests() + .state(GHIssueState.OPEN) + .head("hub4j-test-org:test/stable") + .base("main") + .list() + .toList(); + assertThat(prs, notNullValue()); + assertThat(prs.size(), equalTo(1)); + assertThat(prs.get(0).getHead().getRef(), equalTo("test/stable")); + } - GHPullRequest outdatedPullRequest = repository.createPullRequest(prName, "outdated", "main", "## test"); + /** + * Query pull requests unqualified head. + * + * @throws Exception + * the exception + */ + @Test + public void queryPullRequestsUnqualifiedHead() throws Exception { + GHRepository repo = getRepository(); + // Create PRs from two different branches to main + repo.createPullRequest("queryPullRequestsUnqualifiedHead_stable", "test/stable", "main", null); + repo.createPullRequest("queryPullRequestsUnqualifiedHead_rc", "test/rc", "main", null); - do { - Thread.sleep(5000); - outdatedPullRequest.refresh(); - } while (outdatedPullRequest.getMergeableState().equalsIgnoreCase("unknown")); + // Query by one of the heads and make sure we only get that branch's PR back. + List prs = repo.queryPullRequests() + .state(GHIssueState.OPEN) + .head("test/stable") + .base("main") + .list() + .toList(); + assertThat(prs, notNullValue()); + assertThat(prs.size(), equalTo(1)); + assertThat(prs.get(0).getHead().getRef(), equalTo("test/stable")); + } - assertThat("Pull request is supposed to be not up to date", - outdatedPullRequest.getMergeableState(), - equalTo("behind")); + /** + * Sets the labels. + * + * @throws Exception + * the exception + */ + @Test + // Requires push access to the test repo to pass + public void setLabels() throws Exception { + GHPullRequest p = getRepository().createPullRequest("setLabels", "test/stable", "main", "## test"); + String label = "setLabels_label_name"; + p.setLabels(label); - outdatedPullRequest.updateBranch(); - outdatedPullRequest.refresh(); + Collection labels = getRepository().getPullRequest(p.getNumber()).getLabels(); + assertThat(labels.size(), equalTo(1)); + GHLabel savedLabel = labels.iterator().next(); + assertThat(savedLabel.getName(), equalTo(label)); + assertThat(savedLabel.getId(), notNullValue()); + assertThat(savedLabel.getNodeId(), notNullValue()); + assertThat(savedLabel.isDefault(), is(false)); + } - assertThat("Pull request is supposed to be up to date", outdatedPullRequest.getMergeableState(), not("behind")); + /** + * Adds the labels. + * + * @throws Exception + * the exception + */ + @Test + // Requires push access to the test repo to pass + public void addLabels() throws Exception { + GHPullRequest p = getRepository().createPullRequest("addLabels", "test/stable", "main", "## test"); + String addedLabel1 = "addLabels_label_name_1"; + String addedLabel2 = "addLabels_label_name_2"; + String addedLabel3 = "addLabels_label_name_3"; - outdatedPullRequest.close(); + List resultingLabels = p.addLabels(addedLabel1); + assertThat(resultingLabels.size(), equalTo(1)); + GHLabel ghLabel = resultingLabels.get(0); + assertThat(ghLabel.getName(), equalTo(addedLabel1)); + + int requestCount = mockGitHub.getRequestCount(); + resultingLabels = p.addLabels(addedLabel2, addedLabel3); + // multiple labels can be added with one api call + assertThat(mockGitHub.getRequestCount(), equalTo(requestCount + 1)); + + assertThat(resultingLabels.size(), equalTo(3)); + assertThat(resultingLabels, + containsInAnyOrder(hasProperty("name", equalTo(addedLabel1)), + hasProperty("name", equalTo(addedLabel2)), + hasProperty("name", equalTo(addedLabel3)))); + + // Adding a label which is already present does not throw an error + resultingLabels = p.addLabels(ghLabel); + assertThat(resultingLabels.size(), equalTo(3)); } /** - * Update outdated branches unexpected head. + * Adds the labels concurrency issue. * * @throws Exception * the exception */ @Test - public void updateOutdatedBranchesUnexpectedHead() throws Exception { - String prName = "testUpdateOutdatedBranches"; - String outdatedRefName = "refs/heads/outdated"; - GHRepository repository = gitHub.getOrganization("hub4j-test-org").getRepository("updateOutdatedBranches"); + // Requires push access to the test repo to pass + public void addLabelsConcurrencyIssue() throws Exception { + String addedLabel1 = "addLabelsConcurrencyIssue_label_name_1"; + String addedLabel2 = "addLabelsConcurrencyIssue_label_name_2"; - GHRef outdatedRef = repository.getRef(outdatedRefName); - outdatedRef.updateTo("6440189369f9f33b2366556a94dbc26f2cfdd969", true); + GHPullRequest p1 = getRepository() + .createPullRequest("addLabelsConcurrencyIssue", "test/stable", "main", "## test"); + p1.getLabels(); - GHPullRequest outdatedPullRequest = repository.createPullRequest(prName, "outdated", "main", "## test"); + GHPullRequest p2 = getRepository().getPullRequest(p1.getNumber()); + p2.addLabels(addedLabel2); - do { - Thread.sleep(5000); - outdatedPullRequest.refresh(); - } while (outdatedPullRequest.getMergeableState().equalsIgnoreCase("unknown")); + Collection labels = p1.addLabels(addedLabel1); - assertThat("Pull request is supposed to be not up to date", - outdatedPullRequest.getMergeableState(), - equalTo("behind")); + assertThat(labels.size(), equalTo(2)); + assertThat(labels, + containsInAnyOrder(hasProperty("name", equalTo(addedLabel1)), + hasProperty("name", equalTo(addedLabel2)))); + } - outdatedRef.updateTo("f567328eb81270487864963b7d7446953353f2b5", true); + /** + * Removes the labels. + * + * @throws Exception + * the exception + */ + @Test + // Requires push access to the test repo to pass + public void removeLabels() throws Exception { + GHPullRequest p = getRepository().createPullRequest("removeLabels", "test/stable", "main", "## test"); + String label1 = "removeLabels_label_name_1"; + String label2 = "removeLabels_label_name_2"; + String label3 = "removeLabels_label_name_3"; + p.setLabels(label1, label2, label3); + + Collection labels = getRepository().getPullRequest(p.getNumber()).getLabels(); + assertThat(labels.size(), equalTo(3)); + GHLabel ghLabel3 = labels.stream().filter(label -> label3.equals(label.getName())).findFirst().get(); + int requestCount = mockGitHub.getRequestCount(); + List resultingLabels = p.removeLabels(label2, label3); + // each label deleted is a separate api call + assertThat(mockGitHub.getRequestCount(), equalTo(requestCount + 2)); + + assertThat(resultingLabels.size(), equalTo(1)); + assertThat(resultingLabels.get(0).getName(), equalTo(label1)); + + // Removing some labels that are not present does not throw + // This is consistent with earlier behavior and with addLabels() + p.removeLabels(ghLabel3); + + // Calling removeLabel() on label that is not present will throw try { - outdatedPullRequest.updateBranch(); - } catch (HttpException e) { - assertThat(e, instanceOf(HttpException.class)); - assertThat(e.toString(), containsString("expected head sha didn’t match current head ref.")); + p.removeLabel(label3); + fail("Expected GHFileNotFoundException"); + } catch (GHFileNotFoundException e) { + assertThat(e.getMessage(), containsString("Label does not exist")); } + } - outdatedPullRequest.close(); + /** + * Sets the assignee. + * + * @throws Exception + * the exception + */ + @Test + // Requires push access to the test repo to pass + public void setAssignee() throws Exception { + GHPullRequest p = getRepository().createPullRequest("setAssignee", "test/stable", "main", "## test"); + GHMyself user = gitHub.getMyself(); + p.assignTo(user); + + assertThat(getRepository().getPullRequest(p.getNumber()).getAssignee(), equalTo(user)); } - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + /** + * Gets the user test. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void getUserTest() throws IOException { + GHPullRequest p = getRepository().createPullRequest("getUserTest", "test/stable", "main", "## test"); + GHPullRequest prSingle = getRepository().getPullRequest(p.getNumber()); + assertThat(prSingle.getUser().root(), notNullValue()); + prSingle.getMergeable(); + assertThat(prSingle.getUser().root(), notNullValue()); + + PagedIterable ghPullRequests = getRepository().queryPullRequests() + .state(GHIssueState.OPEN) + .list(); + for (GHPullRequest pr : ghPullRequests) { + assertThat(pr.getUser().root(), notNullValue()); + pr.getMergeable(); + assertThat(pr.getUser().root(), notNullValue()); + } + } + + /** + * Check non existent reviewer. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + // @Test + // public void checkNonExistentReviewer() throws IOException { + // // PR id is based on https://github.com/sahansera/TestRepo/pull/1 + // final GHPullRequest pullRequest = getRepository().getPullRequest(1); + // final Optional review = pullRequest.listReviews().toList().stream().findFirst(); + // final GHUser reviewer = review.get().getUser(); + + // assertThat(pullRequest.getRequestedReviewers(), is(empty())); + // assertThat(review, notNullValue()); + // assertThat(reviewer, is(nullValue())); + // } + + /** + * Check non existent author. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void checkNonExistentAuthor() throws IOException { + // PR id is based on https://github.com/sahansera/TestRepo/pull/2 + final GHPullRequest pullRequest = getRepository().getPullRequest(2); + + assertThat(pullRequest.getUser(), is(notNullValue())); + assertThat(pullRequest.getUser().login, is("ghost")); + } + + /** + * Check pull request reviewer. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void checkPullRequestReviewer() throws IOException { + // PR id is based on https://github.com/sahansera/TestRepo/pull/6 + final GHPullRequest pullRequest = getRepository().getPullRequest(6); + final Optional review = pullRequest.listReviews().toList().stream().findFirst(); + final GHUser reviewer = review.get().getUser(); + + assertThat(review, notNullValue()); + assertThat(reviewer, notNullValue()); + } + + /** + * Create/Delete reaction for pull requests. + * + * @throws Exception + * the exception + */ + @Test + public void reactions() throws Exception { + String name = "createPullRequest"; + GHRepository repo = getRepository(); + GHPullRequest p = repo.createPullRequest(name, "test/stable", "main", "## test"); + + assertThat(p.listReactions().toList(), hasSize(0)); + GHReaction reaction = p.createReaction(ReactionContent.CONFUSED); + assertThat(p.listReactions().toList(), hasSize(1)); + + p.deleteReaction(reaction); + assertThat(p.listReactions().toList(), hasSize(0)); + } + + /** + * Test refreshing a PR coming from the search results. + * + * @throws Exception + * the exception + */ + @Test + public void refreshFromSearchResults() throws Exception { + // To re-record, uncomment the Thread.sleep() calls below + snapshotNotAllowed(); + + String prName = "refreshFromSearchResults"; + GHRepository repository = getRepository(); + + repository.createPullRequest(prName, "test/stable", "main", "## test"); + + // we need to wait a bit for the pull request to be indexed by GitHub + // Thread.sleep(2000); + + GHPullRequest pullRequestFromSearchResults = repository.searchPullRequests() + .isOpen() + .titleLike(prName) + .list() + .toList() + .get(0); + + pullRequestFromSearchResults.getMergeableState(); + + // wait a bit for the mergeable state to get populated + // Thread.sleep(5000); + + assertThat("Pull request is supposed to have been refreshed and have a mergeable state", + pullRequestFromSearchResults.getMergeableState(), + equalTo("clean")); + + pullRequestFromSearchResults.close(); } /** @@ -1144,4 +1046,8 @@ private GHRepository getRepository(GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } } diff --git a/src/test/java/org/kohsuke/github/GHRateLimitTest.java b/src/test/java/org/kohsuke/github/GHRateLimitTest.java index 66fcc21df1..5ec59ebb50 100644 --- a/src/test/java/org/kohsuke/github/GHRateLimitTest.java +++ b/src/test/java/org/kohsuke/github/GHRateLimitTest.java @@ -7,7 +7,6 @@ import java.io.IOException; import java.time.Duration; -import java.time.Instant; import java.util.Date; import java.util.HashMap; @@ -39,16 +38,12 @@ */ public class GHRateLimitTest extends AbstractGitHubWireMockTest { - private static GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); - } + /** The rate limit. */ + GHRateLimit rateLimit = null; /** The previous limit. */ GHRateLimit previousLimit = null; - /** The rate limit. */ - GHRateLimit rateLimit = null; - /** * Instantiates a new GH rate limit test. */ @@ -56,6 +51,202 @@ public GHRateLimitTest() { useDefaultGitHub = false; } + /** + * Gets the wire mock options. + * + * @return the wire mock options + */ + @Override + protected WireMockConfiguration getWireMockOptions() { + return super.getWireMockOptions().extensions(templating.newResponseTransformer()); + } + + /** + * Test git hub rate limit. + * + * @throws Exception + * the exception + */ + @Test + public void testGitHubRateLimit() throws Exception { + // Customized response that templates the date to keep things working + snapshotNotAllowed(); + GHRateLimit.UnknownLimitRecord.reset(); + + assertThat(mockGitHub.getRequestCount(), equalTo(0)); + + // 4897 is just the what the limit was when the snapshot was taken + previousLimit = GHRateLimit.fromRecord( + new GHRateLimit.Record(5000, + 4897, + (templating.testStartDate.getTime() + Duration.ofHours(1).toMillis()) / 1000L), + RateLimitTarget.CORE); + + // ------------------------------------------------------------- + // /user gets response with rate limit information + gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); + gitHub.getMyself(); + + assertThat(mockGitHub.getRequestCount(), equalTo(1)); + + // Since we already had rate limit info these don't request again + rateLimit = gitHub.lastRateLimit(); + verifyRateLimitValues(previousLimit, previousLimit.getRemaining()); + previousLimit = rateLimit; + + GHRateLimit headerRateLimit = rateLimit; + + // Give this a moment + Thread.sleep(1500); + + // ratelimit() uses cached rate limit if available and not expired + assertThat(gitHub.rateLimit(), sameInstance(headerRateLimit)); + + assertThat(mockGitHub.getRequestCount(), equalTo(1)); + + // Give this a moment + Thread.sleep(1500); + + // Always requests new info + rateLimit = gitHub.getRateLimit(); + assertThat(mockGitHub.getRequestCount(), equalTo(2)); + + // Because remaining and reset date are unchanged in core, the header should be unchanged as well + // But the overall instance has changed because of filling in of unknown data. + assertThat(gitHub.lastRateLimit(), not(sameInstance(headerRateLimit))); + // Identical Records should be preserved even when GHRateLimit is merged + assertThat(gitHub.lastRateLimit().getCore(), sameInstance(headerRateLimit.getCore())); + assertThat(gitHub.lastRateLimit().getSearch(), not(sameInstance(headerRateLimit.getSearch()))); + headerRateLimit = gitHub.lastRateLimit(); + + // rate limit request is free, remaining is unchanged + verifyRateLimitValues(previousLimit, previousLimit.getRemaining()); + previousLimit = rateLimit; + + // Give this a moment + Thread.sleep(1500); + + // Always requests new info + rateLimit = gitHub.getRateLimit(); + assertThat(mockGitHub.getRequestCount(), equalTo(3)); + + // Because remaining and reset date are unchanged, the header should be unchanged as well + assertThat(gitHub.lastRateLimit(), sameInstance(headerRateLimit)); + + // rate limit request is free, remaining is unchanged + verifyRateLimitValues(previousLimit, previousLimit.getRemaining()); + previousLimit = rateLimit; + + gitHub.getOrganization(GITHUB_API_TEST_ORG); + assertThat(mockGitHub.getRequestCount(), equalTo(4)); + + // Because remaining has changed the header should be different + assertThat(gitHub.lastRateLimit(), not(sameInstance(headerRateLimit))); + assertThat(gitHub.lastRateLimit(), not(equalTo(headerRateLimit))); + rateLimit = gitHub.lastRateLimit(); + + // Org costs limit to query + verifyRateLimitValues(previousLimit, previousLimit.getRemaining() - 1); + + previousLimit = rateLimit; + headerRateLimit = rateLimit; + + // ratelimit() should prefer headerRateLimit when it is most recent and not expired + assertThat(gitHub.rateLimit(), sameInstance(headerRateLimit)); + + assertThat(mockGitHub.getRequestCount(), equalTo(4)); + + // AT THIS POINT WE SIMULATE A RATE LIMIT RESET + + // Give this a moment + Thread.sleep(2000); + + // Always requests new info + rateLimit = gitHub.getRateLimit(); + assertThat(mockGitHub.getRequestCount(), equalTo(5)); + + // rate limit request is free, remaining is unchanged date is later + verifyRateLimitValues(previousLimit, previousLimit.getRemaining(), true); + previousLimit = rateLimit; + + // When getRateLimit() succeeds, cached rate limit updates as usual as well (if needed) + assertThat(gitHub.rateLimit(), sameInstance(rateLimit)); + + // Verify different record instances can be compared + assertThat(gitHub.rateLimit().getCore(), equalTo(rateLimit.getCore())); + + // Verify different instances can be compared + // TODO: This is not work currently because the header rate limit has unknowns for records other than core. + // assertThat(gitHub.rateLimit(), equalTo(rateLimit)); + + assertThat(gitHub.rateLimit(), not(sameInstance(headerRateLimit))); + assertThat(gitHub.rateLimit(), sameInstance(gitHub.lastRateLimit())); + headerRateLimit = gitHub.lastRateLimit(); + + assertThat(mockGitHub.getRequestCount(), equalTo(5)); + + // Verify the requesting a search url updates the search rate limit + assertThat(gitHub.lastRateLimit().getSearch().getRemaining(), equalTo(30)); + + HashMap searchResult = (HashMap) gitHub.createRequest() + .rateLimit(RateLimitTarget.SEARCH) + .setRawUrlPath(mockGitHub.apiServer().baseUrl() + + "/search/repositories?q=tetris+language%3Aassembly&sort=stars&order=desc") + .fetch(HashMap.class); + + assertThat(searchResult.get("total_count"), equalTo(1918)); + + assertThat(mockGitHub.getRequestCount(), equalTo(6)); + + assertThat(gitHub.lastRateLimit(), not(sameInstance(headerRateLimit))); + assertThat(gitHub.lastRateLimit().getCore(), sameInstance(headerRateLimit.getCore())); + assertThat(gitHub.lastRateLimit().getSearch(), not(sameInstance(headerRateLimit.getSearch()))); + assertThat(gitHub.lastRateLimit().getSearch().getRemaining(), equalTo(29)); + + PagedSearchIterable searchResult2 = gitHub.searchRepositories() + .q("tetris") + .language("assembly") + .sort(GHRepositorySearchBuilder.Sort.STARS) + .order(GHDirection.DESC) + .list(); + + assertThat(searchResult2.getTotalCount(), equalTo(1918)); + + assertThat(mockGitHub.getRequestCount(), equalTo(7)); + + assertThat(gitHub.lastRateLimit(), not(sameInstance(headerRateLimit))); + assertThat(gitHub.lastRateLimit().getCore(), sameInstance(headerRateLimit.getCore())); + assertThat(gitHub.lastRateLimit().getSearch(), not(sameInstance(headerRateLimit.getSearch()))); + assertThat(gitHub.lastRateLimit().getSearch().getRemaining(), equalTo(28)); + } + + private void verifyRateLimitValues(GHRateLimit previousLimit, int remaining) { + verifyRateLimitValues(previousLimit, remaining, false); + } + + private void verifyRateLimitValues(GHRateLimit previousLimit, int remaining, boolean changedResetDate) { + // Basic checks of values + assertThat(rateLimit, notNullValue()); + assertThat(rateLimit.getLimit(), equalTo(previousLimit.getLimit())); + assertThat(rateLimit.getRemaining(), equalTo(remaining)); + + // Check that the reset date of the current limit is not older than the previous one + long diffMillis = rateLimit.getResetDate().getTime() - previousLimit.getResetDate().getTime(); + + assertThat(diffMillis, greaterThanOrEqualTo(0L)); + if (changedResetDate) { + assertThat(diffMillis, greaterThan(1000L)); + } else { + assertThat(diffMillis, lessThanOrEqualTo(1000L)); + } + + // Additional checks for record values + assertThat(rateLimit.getCore().getLimit(), equalTo(rateLimit.getLimit())); + assertThat(rateLimit.getCore().getRemaining(), equalTo(rateLimit.getRemaining())); + assertThat(rateLimit.getCore().getResetEpochSeconds(), equalTo(rateLimit.getResetEpochSeconds())); + assertThat(rateLimit.getCore().getResetDate(), equalTo(rateLimit.getResetDate())); + } + /** * Test git hub enterprise does not have rate limit. * @@ -71,7 +262,7 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws Exception { assertThat(mockGitHub.getRequestCount(), equalTo(0)); GHRateLimit rateLimit = null; - Instant lastReset = Instant.ofEpochMilli(System.currentTimeMillis() / 1000L); + Date lastReset = new Date(System.currentTimeMillis() / 1000L); // Give this a moment Thread.sleep(1500); @@ -88,8 +279,8 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws Exception { assertThat(rateLimit.getCore(), instanceOf(GHRateLimit.UnknownLimitRecord.class)); assertThat(rateLimit.getLimit(), equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); assertThat(rateLimit.getRemaining(), equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); - assertThat(rateLimit.getResetDate().compareTo(Date.from(lastReset)), equalTo(1)); - lastReset = rateLimit.getCore().getResetInstant(); + assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(1)); + lastReset = rateLimit.getResetDate(); assertThat(mockGitHub.getRequestCount(), equalTo(1)); @@ -115,8 +306,8 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws Exception { assertThat(rateLimit.getLimit(), equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); assertThat(rateLimit.getRemaining(), equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); // Same unknown instance is reused for a while - assertThat(rateLimit.getResetDate().compareTo(Date.from(lastReset)), equalTo(0)); - lastReset = rateLimit.getCore().getResetInstant(); + assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(0)); + lastReset = rateLimit.getResetDate(); assertThat(mockGitHub.getRequestCount(), equalTo(3)); @@ -135,7 +326,7 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws Exception { assertThat(rateLimit.getLimit(), equalTo(GHRateLimit.UnknownLimitRecord.unknownLimit)); assertThat(rateLimit.getRemaining(), equalTo(GHRateLimit.UnknownLimitRecord.unknownRemaining)); // When not expired, unknowns do not replace each other so last reset remains unchanged - assertThat(rateLimit.getResetDate().compareTo(Date.from(lastReset)), equalTo(0)); + assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(0)); // Give this a moment Thread.sleep(1500); @@ -157,8 +348,8 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws Exception { assertThat(rateLimit, notNullValue()); assertThat(rateLimit.getLimit(), equalTo(5000)); assertThat(rateLimit.getRemaining(), equalTo(4978)); - assertThat(rateLimit.getResetDate().compareTo(Date.from(lastReset)), equalTo(1)); - lastReset = rateLimit.getCore().getResetInstant(); + assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(1)); + lastReset = rateLimit.getResetDate(); // When getting only header updates, the unknowns are also expired assertThat(rateLimit.getSearch().isExpired(), is(true)); @@ -192,7 +383,7 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws Exception { // 11 requests since previous api call // This verifies that header rate limit info is recorded even for /rate_limit endpoint and 404 response assertThat(rateLimit.getRemaining(), equalTo(4967)); - assertThat(rateLimit.getResetDate().compareTo(Date.from(lastReset)), equalTo(0)); + assertThat(rateLimit.getResetDate().compareTo(lastReset), equalTo(0)); // getRateLimit() uses headerRateLimit if /rate_limit returns a 404 // and headerRateLimit is available and not expired @@ -243,162 +434,37 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws Exception { } /** - * Test git hub rate limit. + * Test git hub rate limit with bad data. * * @throws Exception * the exception */ @Test - public void testGitHubRateLimit() throws Exception { - // Customized response that templates the date to keep things working + public void testGitHubRateLimitWithBadData() throws Exception { snapshotNotAllowed(); - GHRateLimit.UnknownLimitRecord.reset(); - - assertThat(mockGitHub.getRequestCount(), equalTo(0)); - - // 4897 is just the what the limit was when the snapshot was taken - previousLimit = GHRateLimit.fromRecord( - new GHRateLimit.Record(5000, - 4897, - (templating.testStartDate.getTime() + Duration.ofHours(1).toMillis()) / 1000L), - RateLimitTarget.CORE); - - // ------------------------------------------------------------- - // /user gets response with rate limit information gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); gitHub.getMyself(); + try { + gitHub.getRateLimit(); + fail("Invalid rate limit missing some records should throw"); + } catch (Exception e) { + assertThat(e, instanceOf(HttpException.class)); + assertThat(e.getCause(), instanceOf(ValueInstantiationException.class)); + assertThat(e.getCause().getMessage(), + containsString( + "Cannot construct instance of `org.kohsuke.github.GHRateLimit`, problem: `java.lang.NullPointerException`")); + } - assertThat(mockGitHub.getRequestCount(), equalTo(1)); - - // Since we already had rate limit info these don't request again - rateLimit = gitHub.lastRateLimit(); - verifyRateLimitValues(previousLimit, previousLimit.getRemaining()); - previousLimit = rateLimit; - - GHRateLimit headerRateLimit = rateLimit; - - // Give this a moment - Thread.sleep(1500); - - // ratelimit() uses cached rate limit if available and not expired - assertThat(gitHub.rateLimit(), sameInstance(headerRateLimit)); - - assertThat(mockGitHub.getRequestCount(), equalTo(1)); - - // Give this a moment - Thread.sleep(1500); - - // Always requests new info - rateLimit = gitHub.getRateLimit(); - assertThat(mockGitHub.getRequestCount(), equalTo(2)); - - // Because remaining and reset date are unchanged in core, the header should be unchanged as well - // But the overall instance has changed because of filling in of unknown data. - assertThat(gitHub.lastRateLimit(), not(sameInstance(headerRateLimit))); - // Identical Records should be preserved even when GHRateLimit is merged - assertThat(gitHub.lastRateLimit().getCore(), sameInstance(headerRateLimit.getCore())); - assertThat(gitHub.lastRateLimit().getSearch(), not(sameInstance(headerRateLimit.getSearch()))); - headerRateLimit = gitHub.lastRateLimit(); - - // rate limit request is free, remaining is unchanged - verifyRateLimitValues(previousLimit, previousLimit.getRemaining()); - previousLimit = rateLimit; - - // Give this a moment - Thread.sleep(1500); - - // Always requests new info - rateLimit = gitHub.getRateLimit(); - assertThat(mockGitHub.getRequestCount(), equalTo(3)); - - // Because remaining and reset date are unchanged, the header should be unchanged as well - assertThat(gitHub.lastRateLimit(), sameInstance(headerRateLimit)); - - // rate limit request is free, remaining is unchanged - verifyRateLimitValues(previousLimit, previousLimit.getRemaining()); - previousLimit = rateLimit; - - gitHub.getOrganization(GITHUB_API_TEST_ORG); - assertThat(mockGitHub.getRequestCount(), equalTo(4)); - - // Because remaining has changed the header should be different - assertThat(gitHub.lastRateLimit(), not(sameInstance(headerRateLimit))); - assertThat(gitHub.lastRateLimit(), not(equalTo(headerRateLimit))); - rateLimit = gitHub.lastRateLimit(); - - // Org costs limit to query - verifyRateLimitValues(previousLimit, previousLimit.getRemaining() - 1); - - previousLimit = rateLimit; - headerRateLimit = rateLimit; - - // ratelimit() should prefer headerRateLimit when it is most recent and not expired - assertThat(gitHub.rateLimit(), sameInstance(headerRateLimit)); - - assertThat(mockGitHub.getRequestCount(), equalTo(4)); - - // AT THIS POINT WE SIMULATE A RATE LIMIT RESET - - // Give this a moment - Thread.sleep(2000); - - // Always requests new info - rateLimit = gitHub.getRateLimit(); - assertThat(mockGitHub.getRequestCount(), equalTo(5)); - - // rate limit request is free, remaining is unchanged date is later - verifyRateLimitValues(previousLimit, previousLimit.getRemaining(), true); - previousLimit = rateLimit; - - // When getRateLimit() succeeds, cached rate limit updates as usual as well (if needed) - assertThat(gitHub.rateLimit(), sameInstance(rateLimit)); - - // Verify different record instances can be compared - assertThat(gitHub.rateLimit().getCore(), equalTo(rateLimit.getCore())); - - // Verify different instances can be compared - // TODO: This is not work currently because the header rate limit has unknowns for records other than core. - // assertThat(gitHub.rateLimit(), equalTo(rateLimit)); - - assertThat(gitHub.rateLimit(), not(sameInstance(headerRateLimit))); - assertThat(gitHub.rateLimit(), sameInstance(gitHub.lastRateLimit())); - headerRateLimit = gitHub.lastRateLimit(); - - assertThat(mockGitHub.getRequestCount(), equalTo(5)); - - // Verify the requesting a search url updates the search rate limit - assertThat(gitHub.lastRateLimit().getSearch().getRemaining(), equalTo(30)); - - HashMap searchResult = gitHub.createRequest() - .rateLimit(RateLimitTarget.SEARCH) - .setRawUrlPath(mockGitHub.apiServer().baseUrl() - + "/search/repositories?q=tetris+language%3Aassembly&sort=stars&order=desc") - .fetch(HashMap.class); - - assertThat(searchResult.get("total_count"), equalTo(1918)); - - assertThat(mockGitHub.getRequestCount(), equalTo(6)); - - assertThat(gitHub.lastRateLimit(), not(sameInstance(headerRateLimit))); - assertThat(gitHub.lastRateLimit().getCore(), sameInstance(headerRateLimit.getCore())); - assertThat(gitHub.lastRateLimit().getSearch(), not(sameInstance(headerRateLimit.getSearch()))); - assertThat(gitHub.lastRateLimit().getSearch().getRemaining(), equalTo(29)); - - PagedSearchIterable searchResult2 = gitHub.searchRepositories() - .q("tetris") - .language("assembly") - .sort(GHRepositorySearchBuilder.Sort.STARS) - .order(GHDirection.DESC) - .list(); - - assertThat(searchResult2.getTotalCount(), equalTo(1918)); - - assertThat(mockGitHub.getRequestCount(), equalTo(7)); + try { + gitHub.getRateLimit(); + fail("Invalid rate limit record missing a value should throw"); + } catch (Exception e) { + assertThat(e, instanceOf(HttpException.class)); + assertThat(e.getCause(), instanceOf(MismatchedInputException.class)); + assertThat(e.getCause().getMessage(), + containsString("Missing required creator property 'reset' (index 2)")); + } - assertThat(gitHub.lastRateLimit(), not(sameInstance(headerRateLimit))); - assertThat(gitHub.lastRateLimit().getCore(), sameInstance(headerRateLimit.getCore())); - assertThat(gitHub.lastRateLimit().getSearch(), not(sameInstance(headerRateLimit.getSearch()))); - assertThat(gitHub.lastRateLimit().getSearch().getRemaining(), equalTo(28)); } /** @@ -424,40 +490,6 @@ public void testGitHubRateLimitExpirationServerFiveMinutesBehind() throws Except executeExpirationTest(); } - /** - * Test git hub rate limit with bad data. - * - * @throws Exception - * the exception - */ - @Test - public void testGitHubRateLimitWithBadData() throws Exception { - snapshotNotAllowed(); - gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); - gitHub.getMyself(); - try { - gitHub.getRateLimit(); - fail("Invalid rate limit missing some records should throw"); - } catch (Exception e) { - assertThat(e, instanceOf(HttpException.class)); - assertThat(e.getCause(), instanceOf(ValueInstantiationException.class)); - assertThat(e.getCause().getMessage(), - containsString( - "Cannot construct instance of `org.kohsuke.github.GHRateLimit`, problem: `java.lang.NullPointerException`")); - } - - try { - gitHub.getRateLimit(); - fail("Invalid rate limit record missing a value should throw"); - } catch (Exception e) { - assertThat(e, instanceOf(HttpException.class)); - assertThat(e.getCause(), instanceOf(MismatchedInputException.class)); - assertThat(e.getCause().getMessage(), - containsString("Missing required creator property 'reset' (index 2)")); - } - - } - private void executeExpirationTest() throws Exception { // Customized response that templates the date to keep things working snapshotNotAllowed(); @@ -555,42 +587,8 @@ private void executeExpirationTest() throws Exception { assertThat(mockGitHub.getRequestCount(), equalTo(3)); } - private void verifyRateLimitValues(GHRateLimit previousLimit, int remaining) { - verifyRateLimitValues(previousLimit, remaining, false); - } - - private void verifyRateLimitValues(GHRateLimit previousLimit, int remaining, boolean changedResetDate) { - // Basic checks of values - assertThat(rateLimit, notNullValue()); - assertThat(rateLimit.getLimit(), equalTo(previousLimit.getLimit())); - assertThat(rateLimit.getRemaining(), equalTo(remaining)); - - // Check that the reset date of the current limit is not older than the previous one - long diffMillis = rateLimit.getCore().getResetInstant().toEpochMilli() - - previousLimit.getCore().getResetInstant().toEpochMilli(); - - assertThat(diffMillis, greaterThanOrEqualTo(0L)); - if (changedResetDate) { - assertThat(diffMillis, greaterThan(1000L)); - } else { - assertThat(diffMillis, lessThanOrEqualTo(1000L)); - } - - // Additional checks for record values - assertThat(rateLimit.getCore().getLimit(), equalTo(rateLimit.getLimit())); - assertThat(rateLimit.getCore().getRemaining(), equalTo(rateLimit.getRemaining())); - assertThat(rateLimit.getCore().getResetEpochSeconds(), equalTo(rateLimit.getResetEpochSeconds())); - assertThat(rateLimit.getCore().getResetDate(), equalTo(rateLimit.getResetDate())); - } - - /** - * Gets the wire mock options. - * - * @return the wire mock options - */ - @Override - protected WireMockConfiguration getWireMockOptions() { - return super.getWireMockOptions().extensions(templating.newResponseTransformer()); + private static GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); } } diff --git a/src/test/java/org/kohsuke/github/GHReleaseTest.java b/src/test/java/org/kohsuke/github/GHReleaseTest.java index 1a4b5a79d4..7d907c4335 100644 --- a/src/test/java/org/kohsuke/github/GHReleaseTest.java +++ b/src/test/java/org/kohsuke/github/GHReleaseTest.java @@ -3,8 +3,6 @@ import org.junit.Test; import org.kohsuke.github.GHReleaseBuilder.MakeLatest; -import java.util.Date; - import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThrows; @@ -21,28 +19,24 @@ public GHReleaseTest() { } /** - * Test create double release fails. + * Test create simple release. * * @throws Exception * the exception */ @Test - public void testCreateDoubleReleaseFails() throws Exception { + public void testCreateSimpleRelease() throws Exception { GHRepository repo = gitHub.getRepository("hub4j-test-org/testCreateRelease"); String tagName = mockGitHub.getMethodName(); - - GHRelease release = repo.createRelease(tagName).create(); - + GHRelease release = repo.createRelease(tagName).categoryName("announcements").prerelease(false).create(); try { GHRelease releaseCheck = repo.getRelease(release.getId()); - assertThat(releaseCheck, notNullValue()); - HttpException httpException = assertThrows(HttpException.class, () -> { - repo.createRelease(tagName).create(); - }); - - assertThat(httpException.getResponseCode(), is(422)); + assertThat(releaseCheck, notNullValue()); + assertThat(releaseCheck.getTagName(), is(tagName)); + assertThat(releaseCheck.isPrerelease(), is(false)); + assertThat(releaseCheck.getDiscussionUrl(), notNullValue()); } finally { release.delete(); assertThat(repo.getRelease(release.getId()), nullValue()); @@ -50,24 +44,24 @@ public void testCreateDoubleReleaseFails() throws Exception { } /** - * Tests creation of the release with `generate_release_notes` parameter on. + * Test create simple release without discussion. * * @throws Exception - * if any failure has happened. + * the exception */ @Test - public void testCreateReleaseWithNotes() throws Exception { + public void testCreateSimpleReleaseWithoutDiscussion() throws Exception { GHRepository repo = gitHub.getRepository("hub4j-test-org/testCreateRelease"); String tagName = mockGitHub.getMethodName(); - GHRelease release = new GHReleaseBuilder(repo, tagName).generateReleaseNotes(true).create(); + GHRelease release = repo.createRelease(tagName).create(); + try { GHRelease releaseCheck = repo.getRelease(release.getId()); assertThat(releaseCheck, notNullValue()); assertThat(releaseCheck.getTagName(), is(tagName)); - assertThat(releaseCheck.isPrerelease(), is(false)); - assertThat(releaseCheck.getDiscussionUrl(), notNullValue()); + assertThat(releaseCheck.getDiscussionUrl(), nullValue()); } finally { release.delete(); assertThat(repo.getRelease(release.getId()), nullValue()); @@ -75,78 +69,82 @@ public void testCreateReleaseWithNotes() throws Exception { } /** - * Test create release with unknown category fails. + * Test create double release fails. * * @throws Exception * the exception */ @Test - public void testCreateReleaseWithUnknownCategoryFails() throws Exception { + public void testCreateDoubleReleaseFails() throws Exception { GHRepository repo = gitHub.getRepository("hub4j-test-org/testCreateRelease"); String tagName = mockGitHub.getMethodName(); - String releaseName = "release-" + tagName; - assertThrows(GHFileNotFoundException.class, () -> { - repo.createRelease(tagName) - .name(releaseName) - .categoryName("an invalid cateogry") - .prerelease(false) - .create(); - }); + GHRelease release = repo.createRelease(tagName).create(); + + try { + GHRelease releaseCheck = repo.getRelease(release.getId()); + assertThat(releaseCheck, notNullValue()); + + HttpException httpException = assertThrows(HttpException.class, () -> { + repo.createRelease(tagName).create(); + }); + + assertThat(httpException.getResponseCode(), is(422)); + } finally { + release.delete(); + assertThat(repo.getRelease(release.getId()), nullValue()); + } } /** - * Test create simple release. + * Test create release with unknown category fails. * * @throws Exception * the exception */ @Test - public void testCreateSimpleRelease() throws Exception { + public void testCreateReleaseWithUnknownCategoryFails() throws Exception { GHRepository repo = gitHub.getRepository("hub4j-test-org/testCreateRelease"); String tagName = mockGitHub.getMethodName(); - GHRelease release = repo.createRelease(tagName).categoryName("announcements").prerelease(false).create(); - try { - GHRelease releaseCheck = repo.getRelease(release.getId()); - - assertThat(releaseCheck, notNullValue()); - assertThat(releaseCheck.getTagName(), is(tagName)); - assertThat(releaseCheck.isPrerelease(), is(false)); - assertThat(releaseCheck.isDraft(), is(false)); - assertThat(releaseCheck.getAssetsUrl(), endsWith("/assets")); - assertThat(releaseCheck.getDiscussionUrl(), notNullValue()); - assertThat(releaseCheck.getCreatedAt(), equalTo(GitHubClient.parseInstant("2021-06-02T21:59:14Z"))); - assertThat(releaseCheck.getPublished_at(), - equalTo(Date.from(GitHubClient.parseInstant("2021-06-11T06:56:52Z")))); - assertThat(releaseCheck.getPublishedAt(), equalTo(GitHubClient.parseInstant("2021-06-11T06:56:52Z"))); + String releaseName = "release-" + tagName; - } finally { - release.delete(); - assertThat(repo.getRelease(release.getId()), nullValue()); - } + assertThrows(GHFileNotFoundException.class, () -> { + repo.createRelease(tagName) + .name(releaseName) + .categoryName("an invalid cateogry") + .prerelease(false) + .create(); + }); } /** - * Test create simple release without discussion. + * Test update release. * * @throws Exception * the exception */ @Test - public void testCreateSimpleReleaseWithoutDiscussion() throws Exception { + public void testUpdateRelease() throws Exception { GHRepository repo = gitHub.getRepository("hub4j-test-org/testCreateRelease"); String tagName = mockGitHub.getMethodName(); - GHRelease release = repo.createRelease(tagName).create(); - + GHRelease release = repo.createRelease(tagName).prerelease(true).create(); try { GHRelease releaseCheck = repo.getRelease(release.getId()); + GHRelease updateCheck = releaseCheck.update().categoryName("announcements").prerelease(false).update(); assertThat(releaseCheck, notNullValue()); assertThat(releaseCheck.getTagName(), is(tagName)); + assertThat(releaseCheck.isPrerelease(), is(true)); assertThat(releaseCheck.getDiscussionUrl(), nullValue()); + + assertThat(updateCheck, notNullValue()); + assertThat(updateCheck.getTagName(), is(tagName)); + assertThat(updateCheck.isPrerelease(), is(false)); + assertThat(updateCheck.getDiscussionUrl(), notNullValue()); + } finally { release.delete(); assertThat(repo.getRelease(release.getId()), nullValue()); @@ -208,31 +206,24 @@ public void testMakeLatestRelease() throws Exception { } /** - * Test update release. + * Tests creation of the release with `generate_release_notes` parameter on. * * @throws Exception - * the exception + * if any failure has happened. */ @Test - public void testUpdateRelease() throws Exception { + public void testCreateReleaseWithNotes() throws Exception { GHRepository repo = gitHub.getRepository("hub4j-test-org/testCreateRelease"); String tagName = mockGitHub.getMethodName(); - GHRelease release = repo.createRelease(tagName).prerelease(true).create(); + GHRelease release = new GHReleaseBuilder(repo, tagName).generateReleaseNotes(true).create(); try { GHRelease releaseCheck = repo.getRelease(release.getId()); - GHRelease updateCheck = releaseCheck.update().categoryName("announcements").prerelease(false).update(); assertThat(releaseCheck, notNullValue()); assertThat(releaseCheck.getTagName(), is(tagName)); - assertThat(releaseCheck.isPrerelease(), is(true)); - assertThat(releaseCheck.getDiscussionUrl(), nullValue()); - - assertThat(updateCheck, notNullValue()); - assertThat(updateCheck.getTagName(), is(tagName)); - assertThat(updateCheck.isPrerelease(), is(false)); - assertThat(updateCheck.getDiscussionUrl(), notNullValue()); - + assertThat(releaseCheck.isPrerelease(), is(false)); + assertThat(releaseCheck.getDiscussionUrl(), notNullValue()); } finally { release.delete(); assertThat(repo.getRelease(release.getId()), nullValue()); diff --git a/src/test/java/org/kohsuke/github/GHRepositoryForkBuilderTest.java b/src/test/java/org/kohsuke/github/GHRepositoryForkBuilderTest.java deleted file mode 100644 index d07d1eb124..0000000000 --- a/src/test/java/org/kohsuke/github/GHRepositoryForkBuilderTest.java +++ /dev/null @@ -1,277 +0,0 @@ -package org.kohsuke.github; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.time.Duration; -import java.util.Map; - -import static org.awaitility.Awaitility.await; -import static org.hamcrest.Matchers.*; - -// TODO: Auto-generated Javadoc - -/** - * The Class GHRepositoryForkBuilderTest. - */ -public class GHRepositoryForkBuilderTest extends AbstractGitHubWireMockTest { - /** - * The type Test fork builder. - */ - class TestForkBuilder extends GHRepositoryForkBuilder { - /** - * The Last sleep millis. - */ - int lastSleepMillis = 0; - /** - * The Sleep count. - */ - int sleepCount = 0; - - /** - * Instantiates a new Test fork builder. - * - * @param repo - * the repo - */ - TestForkBuilder(GHRepository repo) { - super(repo); - } - - @Override - void sleep(int millis) throws IOException { - sleepCount++; - lastSleepMillis = millis; - try { - if (mockGitHub.isUseProxy()) { - Thread.sleep(millis); - } else { - Thread.sleep(1); - } - } catch (InterruptedException e) { - throw (IOException) new InterruptedIOException().initCause(e); - } - } - } - private static final String TARGET_ORG = "nts-api-test-org"; - private int originalInterval; - - private GHRepository repo; - - /** - * Instantiates a new Gh repository fork builder test. - */ - public GHRepositoryForkBuilderTest() { - } - - /** - * Sets up. - * - * @throws Exception - * the exception - */ - @Before - public void setUp() throws Exception { - repo = getTempRepository(); - - originalInterval = GHRepositoryForkBuilder.FORK_RETRY_INTERVAL; - GHRepositoryForkBuilder.FORK_RETRY_INTERVAL = 100; - - if (mockGitHub.isUseProxy()) { - GitHub github = getNonRecordingGitHub(); - GHRepository repo = github.getRepository(this.repo.getFullName()); - String defaultBranch = repo.getDefaultBranch(); - GHRef mainRef = repo.getRef("heads/" + defaultBranch); - String mainSha = mainRef.getObject().getSha(); - - String[] branchNames = { "test-branch1", "test-branch2", "test-branch3" }; - for (String branchName : branchNames) { - repo.createRef("refs/heads/" + branchName, mainSha); - } - } - } - - /** - * Tear down. - */ - @After - public void tearDown() { - GHRepositoryForkBuilder.FORK_RETRY_INTERVAL = originalInterval; - } - - /** - * Test fork. - * - * @throws Exception - * the exception - */ - @Test - public void testFork() throws Exception { - // cover the deprecated fork() method - GHRepository forkedRepo = repo.fork(); - - verifyBasicForkProperties(repo, forkedRepo, repo.getName()); - verifyBranches(forkedRepo, false); - - forkedRepo.delete(); - } - - /** - * Test fork changed name. - * - * @throws Exception - * the exception - */ - @Test - public void testForkChangedName() throws Exception { - String newRepoName = "test-fork-with-new-name"; - TestForkBuilder builder = createBuilder(); - GHRepository forkedRepo = builder.name(newRepoName).create(); - - assertThat(forkedRepo.getName(), equalTo(newRepoName)); - verifyBasicForkProperties(repo, forkedRepo, newRepoName); - verifyBranches(forkedRepo, false); - - forkedRepo.delete(); - } - - /** - * Test fork default branch only. - * - * @throws Exception - * the exception - */ - @Test - public void testForkDefaultBranchOnly() throws Exception { - TestForkBuilder builder = createBuilder(); - GHRepository forkedRepo = builder.defaultBranchOnly(true).create(); - - verifyBasicForkProperties(repo, forkedRepo, repo.getName()); - verifyBranches(forkedRepo, true); - - forkedRepo.delete(); - } - - /** - * Test fork to org. - * - * @throws Exception - * the exception - */ - @Test - public void testForkToOrg() throws Exception { - GHOrganization targetOrg = gitHub.getOrganization(TARGET_ORG); - // equivalent to the deprecated forkTo() method - TestForkBuilder builder = createBuilder(); - GHRepository forkedRepo = builder.organization(targetOrg).create(); - - verifyBasicForkProperties(repo, forkedRepo, repo.getName()); - verifyBranches(forkedRepo, false); - - forkedRepo.delete(); - } - - /** - * Test sleep. - * - * @throws Exception - * the exception - */ - @Test - public void testSleep() throws Exception { - GHRepositoryForkBuilder builder = new GHRepositoryForkBuilder(repo); - Thread.currentThread().interrupt(); - - try { - builder.sleep(100); - fail("Expected InterruptedIOException"); - } catch (InterruptedIOException e) { - assertThat(e, instanceOf(InterruptedIOException.class)); - assertThat(e.getCause(), instanceOf(InterruptedException.class)); - } - } - - /** - * Test timeout message and sleep count. - */ - @Test - public void testTimeoutMessage() { - // For re-recording, use line below to create successful fork test copy, then comment it out and modify json - // response to 404 - // repo.createFork().name("test-message").create(); - - String newRepoName = "test-message"; - try { - - TestForkBuilder builder = createBuilder(); - try { - builder.name(newRepoName).create(); - fail("Expected IOException for timeout"); - } catch (IOException e) { - assertThat(builder.sleepCount, equalTo(10)); - assertThat(builder.lastSleepMillis, equalTo(100)); - assertThat(e.getMessage(), - allOf(containsString("was forked"), - containsString("with name " + newRepoName), - containsString("but can't find the new repository"))); - } - } finally { - GHRepositoryForkBuilder.FORK_RETRY_INTERVAL = originalInterval; - } - } - - /** - * Test timeout org message. - * - * @throws Exception - * the exception - */ - @Test - public void testTimeoutOrgMessage() throws Exception { - GHOrganization targetOrg = gitHub.getOrganization(TARGET_ORG); - // For re-recording, use line below to create successful fork test copy, then comment it out and modify json - // response to 404 - // repo.createFork().organization(targetOrg).create(); - try { - repo.createFork().organization(targetOrg).create(); - fail("Expected IOException for timeout"); - } catch (IOException e) { - assertThat(e.getMessage(), - allOf(containsString("was forked"), - containsString("into " + TARGET_ORG), - containsString("but can't find the new repository"))); - } - } - - private TestForkBuilder createBuilder() { - return new TestForkBuilder(repo); - } - - private void verifyBasicForkProperties(GHRepository original, GHRepository forked, String expectedName) - throws IOException { - GHRepository updatedFork = forked; - - await().atMost(Duration.ofSeconds(30)) - .pollInterval(Duration.ofSeconds(3)) - .until(() -> gitHub.getRepository(forked.getFullName()).isFork()); - - assertThat(updatedFork, notNullValue()); - assertThat(updatedFork.getName(), equalTo(expectedName)); - assertThat(updatedFork.isFork(), is(true)); - assertThat(updatedFork.getParent().getFullName(), equalTo(original.getFullName())); - } - - private void verifyBranches(GHRepository forked, boolean defaultBranchOnly) throws IOException { - Map branches = forked.getBranches(); - if (defaultBranchOnly) { - assertThat(branches.size(), equalTo(1)); - } else { - assertThat(branches.size(), greaterThan(1)); - } - assertThat(branches.containsKey(forked.getDefaultBranch()), is(true)); - } - -} diff --git a/src/test/java/org/kohsuke/github/GHRepositoryRuleTest.java b/src/test/java/org/kohsuke/github/GHRepositoryRuleTest.java index d5f88f3f5d..084e41e159 100644 --- a/src/test/java/org/kohsuke/github/GHRepositoryRuleTest.java +++ b/src/test/java/org/kohsuke/github/GHRepositoryRuleTest.java @@ -29,56 +29,59 @@ public GHRepositoryRuleTest() { } /** - * Tests to cover AlertsThreshold enum. + * Test to cover the constructor of the Parameters class. */ @Test - public void testAlertsThreshold() { - assertThat(AlertsThreshold.ERRORS, is(notNullValue())); + public void testParameters() { + assertThat(Parameters.REQUIRED_DEPLOYMENT_ENVIRONMENTS.getType(), is(notNullValue())); + assertThat(Parameters.REQUIRED_STATUS_CHECKS.getType(), is(notNullValue())); + assertThat(Parameters.OPERATOR.getType(), is(notNullValue())); + assertThat(Parameters.WORKFLOWS.getType(), is(notNullValue())); + assertThat(Parameters.CODE_SCANNING_TOOLS.getType(), is(notNullValue())); + assertThat(new StringParameter("any").getType(), is(notNullValue())); } /** - * Tests to cover CodeScanningTool class. + * Tests to cover StatusCheckConfiguration class. */ @Test - public void testCodeScanningTool() { - CodeScanningTool codeScanningTool = new CodeScanningTool(); - codeScanningTool = new CodeScanningTool(); - assertThat(codeScanningTool.getAlertsThreshold(), is(nullValue())); - assertThat(codeScanningTool.getSecurityAlertsThreshold(), is(nullValue())); - assertThat(codeScanningTool.getTool(), is(nullValue())); + public void testStatusCheckConfiguration() { + StatusCheckConfiguration statusCheckConfiguration = new StatusCheckConfiguration(); + statusCheckConfiguration = new StatusCheckConfiguration(); + assertThat(statusCheckConfiguration.getContext(), is(nullValue())); + assertThat(statusCheckConfiguration.getIntegrationId(), is(nullValue())); } /** - * Tests to cover Operator enum. + * Tests to cover WorkflowFileReference class. */ @Test - public void testOperator() { - assertThat(Operator.ENDS_WITH, is(notNullValue())); + public void testWorkflowFileReference() { + WorkflowFileReference workflowFileReference = new WorkflowFileReference(); + assertThat(workflowFileReference.getPath(), is(nullValue())); + assertThat(workflowFileReference.getRef(), is(nullValue())); + assertThat(workflowFileReference.getRepositoryId(), is(equalTo(0L))); + assertThat(workflowFileReference.getSha(), is(nullValue())); } /** - * Tests that apply on null JsonNode returns null. - * - * @throws Exception - * if something goes wrong. + * Tests to cover CodeScanningTool class. */ @Test - public void testParameterReturnsNullOnNullArg() throws Exception { - Parameter parameter = new StringParameter("any"); - assertThat(parameter.apply(null, null), is(nullValue())); + public void testCodeScanningTool() { + CodeScanningTool codeScanningTool = new CodeScanningTool(); + codeScanningTool = new CodeScanningTool(); + assertThat(codeScanningTool.getAlertsThreshold(), is(nullValue())); + assertThat(codeScanningTool.getSecurityAlertsThreshold(), is(nullValue())); + assertThat(codeScanningTool.getTool(), is(nullValue())); } /** - * Test to cover the constructor of the Parameters class. + * Tests to cover AlertsThreshold enum. */ @Test - public void testParameters() { - assertThat(Parameters.REQUIRED_DEPLOYMENT_ENVIRONMENTS.getType(), is(notNullValue())); - assertThat(Parameters.REQUIRED_STATUS_CHECKS.getType(), is(notNullValue())); - assertThat(Parameters.OPERATOR.getType(), is(notNullValue())); - assertThat(Parameters.WORKFLOWS.getType(), is(notNullValue())); - assertThat(Parameters.CODE_SCANNING_TOOLS.getType(), is(notNullValue())); - assertThat(new StringParameter("any").getType(), is(notNullValue())); + public void testAlertsThreshold() { + assertThat(AlertsThreshold.ERRORS, is(notNullValue())); } /** @@ -90,25 +93,22 @@ public void testSecurityAlertsThreshold() { } /** - * Tests to cover StatusCheckConfiguration class. + * Tests to cover Operator enum. */ @Test - public void testStatusCheckConfiguration() { - StatusCheckConfiguration statusCheckConfiguration = new StatusCheckConfiguration(); - statusCheckConfiguration = new StatusCheckConfiguration(); - assertThat(statusCheckConfiguration.getContext(), is(nullValue())); - assertThat(statusCheckConfiguration.getIntegrationId(), is(nullValue())); + public void testOperator() { + assertThat(Operator.ENDS_WITH, is(notNullValue())); } /** - * Tests to cover WorkflowFileReference class. + * Tests that apply on null JsonNode returns null. + * + * @throws Exception + * if something goes wrong. */ @Test - public void testWorkflowFileReference() { - WorkflowFileReference workflowFileReference = new WorkflowFileReference(); - assertThat(workflowFileReference.getPath(), is(nullValue())); - assertThat(workflowFileReference.getRef(), is(nullValue())); - assertThat(workflowFileReference.getRepositoryId(), is(equalTo(0L))); - assertThat(workflowFileReference.getSha(), is(nullValue())); + public void testParameterReturnsNullOnNullArg() throws Exception { + Parameter parameter = new StringParameter("any"); + assertThat(parameter.apply(null, null), is(nullValue())); } } diff --git a/src/test/java/org/kohsuke/github/GHRepositoryStatisticsTest.java b/src/test/java/org/kohsuke/github/GHRepositoryStatisticsTest.java index 08a9524214..b7e32ce0a8 100644 --- a/src/test/java/org/kohsuke/github/GHRepositoryStatisticsTest.java +++ b/src/test/java/org/kohsuke/github/GHRepositoryStatisticsTest.java @@ -14,20 +14,20 @@ */ public class GHRepositoryStatisticsTest extends AbstractGitHubWireMockTest { - /** The max iterations. */ - public static int MAX_ITERATIONS = 3; - - /** The sleep interval. */ - public static int SLEEP_INTERVAL = 5000; - /** * Create default GHRepositoryStatisticsTest instance */ public GHRepositoryStatisticsTest() { } + /** The max iterations. */ + public static int MAX_ITERATIONS = 3; + + /** The sleep interval. */ + public static int SLEEP_INTERVAL = 5000; + /** - * Test code frequency. + * Test contributor stats. * * @throws IOException * Signals that an I/O exception has occurred. @@ -35,19 +35,10 @@ public GHRepositoryStatisticsTest() { * the interrupted exception */ @Test - @SuppressWarnings("SleepWhileInLoop") - public void testCodeFrequency() throws IOException, InterruptedException { + public void testContributorStats() throws IOException, InterruptedException { // get the statistics - List stats = null; - - for (int i = 0; i < MAX_ITERATIONS; i += 1) { - stats = getRepository().getStatistics().getCodeFrequency(); - if (stats == null) { - Thread.sleep(SLEEP_INTERVAL); - } else { - break; - } - } + PagedIterable stats = getRepository().getStatistics() + .getContributorStats(); // check that the statistics were eventually retrieved if (stats == null) { @@ -56,19 +47,40 @@ public void testCodeFrequency() throws IOException, InterruptedException { } // check the statistics are accurate - // TODO: Perhaps return this as a map with the timestamp as the key? - // Either that or wrap in an object with accessor methods. - Boolean foundWeek = false; - for (GHRepositoryStatistics.CodeFrequency item : stats) { - if (item.getWeekTimestamp() == 1535241600) { - assertThat(item.getAdditions(), equalTo(185L)); - assertThat(item.getDeletions(), equalTo(-243L)); - assertThat(item.toString(), equalTo("Week starting 1535241600 has 185 additions and 243 deletions")); - foundWeek = true; + List list = stats.toList(); + assertThat(list.size(), equalTo(99)); + + // find a particular developer + // TODO: Add an accessor method for this instead of having use a loop. + boolean developerFound = false; + final String authorLogin = "kohsuke"; + for (GHRepositoryStatistics.ContributorStats statsForAuthor : list) { + if (authorLogin.equals(statsForAuthor.getAuthor().getLogin())) { + assertThat(statsForAuthor.getTotal(), equalTo(715)); + assertThat(statsForAuthor.toString(), equalTo("kohsuke made 715 contributions over 494 weeks")); + + List weeks = statsForAuthor.getWeeks(); + assertThat(weeks.size(), equalTo(494)); + + try { + // check a particular week + // TODO: Maybe add a convenience method to get the week + // containing a certain date (Java.Util.Date). + GHRepositoryStatistics.ContributorStats.Week week = statsForAuthor.getWeek(1541289600); + assertThat(week.getNumberOfAdditions(), equalTo(63)); + assertThat(week.getNumberOfDeletions(), equalTo(56)); + assertThat(week.getNumberOfCommits(), equalTo(5)); + assertThat(week.toString(), + equalTo("Week starting 1541289600 - Additions: 63, Deletions: 56, Commits: 5")); + } catch (NoSuchElementException e) { + fail("Did not find week 1546128000"); + } + developerFound = true; break; } } - assertThat("Could not find week starting 1535241600", foundWeek); + + assertThat("Did not find author " + authorLogin, developerFound); } /** @@ -125,7 +137,7 @@ public void testCommitActivity() throws IOException, InterruptedException { } /** - * Test contributor stats. + * Test code frequency. * * @throws IOException * Signals that an I/O exception has occurred. @@ -133,10 +145,19 @@ public void testCommitActivity() throws IOException, InterruptedException { * the interrupted exception */ @Test - public void testContributorStats() throws IOException, InterruptedException { + @SuppressWarnings("SleepWhileInLoop") + public void testCodeFrequency() throws IOException, InterruptedException { // get the statistics - PagedIterable stats = getRepository().getStatistics() - .getContributorStats(); + List stats = null; + + for (int i = 0; i < MAX_ITERATIONS; i += 1) { + stats = getRepository().getStatistics().getCodeFrequency(); + if (stats == null) { + Thread.sleep(SLEEP_INTERVAL); + } else { + break; + } + } // check that the statistics were eventually retrieved if (stats == null) { @@ -145,40 +166,19 @@ public void testContributorStats() throws IOException, InterruptedException { } // check the statistics are accurate - List list = stats.toList(); - assertThat(list.size(), equalTo(99)); - - // find a particular developer - // TODO: Add an accessor method for this instead of having use a loop. - boolean developerFound = false; - final String authorLogin = "kohsuke"; - for (GHRepositoryStatistics.ContributorStats statsForAuthor : list) { - if (authorLogin.equals(statsForAuthor.getAuthor().getLogin())) { - assertThat(statsForAuthor.getTotal(), equalTo(715)); - assertThat(statsForAuthor.toString(), equalTo("kohsuke made 715 contributions over 494 weeks")); - - List weeks = statsForAuthor.getWeeks(); - assertThat(weeks.size(), equalTo(494)); - - try { - // check a particular week - // TODO: Maybe add a convenience method to get the week - // containing a certain date (Java.Util.Date). - GHRepositoryStatistics.ContributorStats.Week week = statsForAuthor.getWeek(1541289600); - assertThat(week.getNumberOfAdditions(), equalTo(63)); - assertThat(week.getNumberOfDeletions(), equalTo(56)); - assertThat(week.getNumberOfCommits(), equalTo(5)); - assertThat(week.toString(), - equalTo("Week starting 1541289600 - Additions: 63, Deletions: 56, Commits: 5")); - } catch (NoSuchElementException e) { - fail("Did not find week 1546128000"); - } - developerFound = true; + // TODO: Perhaps return this as a map with the timestamp as the key? + // Either that or wrap in an object with accessor methods. + Boolean foundWeek = false; + for (GHRepositoryStatistics.CodeFrequency item : stats) { + if (item.getWeekTimestamp() == 1535241600) { + assertThat(item.getAdditions(), equalTo(185L)); + assertThat(item.getDeletions(), equalTo(-243L)); + assertThat(item.toString(), equalTo("Week starting 1535241600 has 185 additions and 243 deletions")); + foundWeek = true; break; } } - - assertThat("Did not find author " + authorLogin, developerFound); + assertThat("Could not find week starting 1535241600", foundWeek); } /** @@ -263,10 +263,6 @@ public void testPunchCard() throws IOException, InterruptedException { assertThat("Hour 10 for Day 2 not found.", hourFound); } - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("github-api"); - } - /** * Gets the repository. * @@ -277,4 +273,8 @@ private GHRepository getRepository(GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository("github-api"); + } } diff --git a/src/test/java/org/kohsuke/github/GHRepositoryTest.java b/src/test/java/org/kohsuke/github/GHRepositoryTest.java index db5d892f85..4a339571a3 100644 --- a/src/test/java/org/kohsuke/github/GHRepositoryTest.java +++ b/src/test/java/org/kohsuke/github/GHRepositoryTest.java @@ -15,7 +15,6 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; -import java.time.Instant; import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; @@ -41,78 +40,105 @@ public GHRepositoryTest() { } /** - * Latest repository exist. + * Gets the repository. + * + * @return the repository + * @throws IOException + * Signals that an I/O exception has occurred. */ - @Test - public void LatestRepositoryExist() { - try { - // add the repository that have latest release - GHRelease release = gitHub.getRepository("kamontat/CheckIDNumber").getLatestRelease(); - assertThat(release.getTagName(), equalTo("v3.0")); - } catch (IOException e) { - e.printStackTrace(); - fail(); - } + protected GHRepository getRepository() throws IOException { + return getRepository(gitHub); + } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); } /** - * Latest repository not exist. + * Test sync of fork + * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void LatestRepositoryNotExist() { - try { - // add the repository that `NOT` have latest release - GHRelease release = gitHub.getRepository("kamontat/Java8Example").getLatestRelease(); - assertThat(release, nullValue()); - } catch (IOException e) { - e.printStackTrace(); - fail(); - } + public void sync() throws IOException { + GHRepository r = getRepository(); + GHBranchSync sync = r.sync("main"); + assertThat(sync.getOwner().getFullName(), equalTo("hub4j-test-org/github-api")); + assertThat(sync.getMessage(), equalTo("Successfully fetched and fast-forwarded from upstream github-api:main")); + assertThat(sync.getMergeType(), equalTo("fast-forward")); + assertThat(sync.getBaseBranch(), equalTo("github-api:main")); } /** - * Adds the collaborators. + * Test sync of repository not a fork * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ - @Test - public void addCollaborators() throws Exception { - GHRepository repo = getRepository(); - GHUser user = getUser(); - List users = new ArrayList<>(); + @Test(expected = HttpException.class) + public void syncNoFork() throws IOException { + GHRepository r = getRepository(); + GHBranchSync sync = r.sync("main"); + fail("Should have thrown an exception"); - users.add(user); - users.add(gitHub.getUser("jimmysombrero2")); - repo.addCollaborators(users, RepositoryRole.from(GHOrganization.Permission.PUSH)); + } - GHPersonSet collabs = repo.getCollaborators(); - GHUser colabUser = collabs.byLogin("jimmysombrero"); - assertThat(colabUser.getAvatarUrl(), equalTo("https://avatars3.githubusercontent.com/u/12157727?v=4")); - assertThat(colabUser.getHtmlUrl().toString(), equalTo("https://github.com/jimmysombrero")); - assertThat(colabUser.getLocation(), nullValue()); + /** + * Test zipball. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testZipball() throws IOException { + getTempRepository().readZip((InputStream inputstream) -> { + return new ByteArrayInputStream(IOUtils.toByteArray(inputstream)); + }, null); + } - assertThat(user.getName(), equalTo(colabUser.getName())); + /** + * Test tarball. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testTarball() throws IOException { + getTempRepository().readTar((InputStream inputstream) -> { + return new ByteArrayInputStream(IOUtils.toByteArray(inputstream)); + }, null); } /** - * Adds the collaborators repo perm. + * Test getters. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void addCollaboratorsRepoPerm() throws Exception { - GHRepository repo = getRepository(); - GHUser user = getUser(); + public void testGetters() throws IOException { + GHRepository r = getTempRepository(); - RepositoryRole role = RepositoryRole.from(GHOrganization.Permission.PULL); - repo.addCollaborators(role, user); + assertThat(r.hasAdminAccess(), is(true)); + assertThat(r.hasDownloads(), is(true)); + assertThat(r.hasIssues(), is(true)); + assertThat(r.hasPages(), is(false)); + assertThat(r.hasProjects(), is(true)); + assertThat(r.hasPullAccess(), is(true)); + assertThat(r.hasPushAccess(), is(true)); + assertThat(r.hasWiki(), is(true)); - GHPersonSet collabs = repo.getCollaborators(); - GHUser colabUser = collabs.byLogin("jgangemi"); + assertThat(r.isAllowMergeCommit(), is(true)); + assertThat(r.isAllowRebaseMerge(), is(true)); + assertThat(r.isAllowSquashMerge(), is(true)); + assertThat(r.isAllowForking(), is(false)); - assertThat(user.getName(), equalTo(colabUser.getName())); + String httpTransport = "https://github.com/hub4j-test-org/temp-testGetters.git"; + assertThat(r.getHttpTransportUrl(), equalTo(httpTransport)); + + assertThat(r.getName(), equalTo("temp-testGetters")); + assertThat(r.getFullName(), equalTo("hub4j-test-org/temp-testGetters")); } /** @@ -138,134 +164,107 @@ public void archive() throws Exception { } /** - * Test demoing the issue with a user having the maintain permission on a repository. - * - * Test checking the permission fallback mechanism in case the Github API changes. The test was recorded at a time a - * new permission was added by mistake. If a re-recording it is needed, you'll like have to manually edit the - * generated mocks to get a non existing permission See - * https://github.com/hub4j/github-api/issues/1671#issuecomment-1577515662 for the details. - * - * @throws IOException - * the exception - */ - @Test - public void cannotRetrievePermissionMaintainUser() throws IOException { - GHRepository r = gitHub.getRepository("hub4j-test-org/maintain-permission-issue"); - GHPermissionType permission = r.getPermission("alecharp"); - assertThat(permission.toString(), is("UNKNOWN")); - } - - /** - * Check stargazers count. + * Checks if is disabled. * * @throws Exception * the exception */ @Test - public void checkStargazersCount() throws Exception { - snapshotNotAllowed(); - GHRepository repo = getTempRepository(); - int stargazersCount = repo.getStargazersCount(); - assertThat(stargazersCount, equalTo(10)); - } + public void isDisabled() throws Exception { + GHRepository r = getRepository(); - /** - * Check watchers count. - * - * @throws Exception - * the exception - */ - @Test - public void checkWatchersCount() throws Exception { - snapshotNotAllowed(); - GHRepository repo = getTempRepository(); - int watchersCount = repo.getWatchersCount(); - assertThat(watchersCount, equalTo(10)); + assertThat(r.isDisabled(), is(false)); } /** - * Creates the dispatch event with client payload. + * Checks if is disabled true. * * @throws Exception * the exception */ @Test - public void createDispatchEventWithClientPayload() throws Exception { - GHRepository repository = getTempRepository(); - Map clientPayload = new HashMap<>(); - clientPayload.put("name", "joe.doe"); - clientPayload.put("list", new ArrayList<>()); - repository.dispatch("test", clientPayload); - } + public void isDisabledTrue() throws Exception { + GHRepository r = getRepository(); - /** - * Creates the dispatch event without client payload. - * - * @throws Exception - * the exception - */ - @Test - public void createDispatchEventWithoutClientPayload() throws Exception { - GHRepository repository = getTempRepository(); - repository.dispatch("test", null); + assertThat(r.isDisabled(), is(true)); } /** - * Creates the secret. + * Gets the branch URL encoded. * * @throws Exception * the exception */ @Test - public void createSecret() throws Exception { - GHRepository repo = getTempRepository(); - repo.createSecret("secret", "encrypted", "public"); + public void getBranch_URLEncoded() throws Exception { + GHRepository repo = getRepository(); + GHBranch branch = repo.getBranch("test/#UrlEncode"); + assertThat(branch.getName(), is("test/#UrlEncode")); } /** - * Creates the signed commit unknown signature type. + * Creates the signed commit verify error. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void createSignedCommitUnknownSignatureType() throws IOException { + public void createSignedCommitVerifyError() throws IOException { GHRepository repository = getRepository(); GHTree ghTree = new GHTreeBuilder(repository).textEntry("a", "", false).create(); GHVerification verification = repository.createCommit() .message("test signing") - .withSignature("unknown") + .withSignature("-----BEGIN PGP SIGNATURE-----\ninvalid\n-----END PGP SIGNATURE-----") .tree(ghTree.getSha()) .create() .getCommitShortInfo() .getVerification(); - assertThat(verification.getReason(), equalTo(UNKNOWN_SIGNATURE_TYPE)); + assertThat(verification.getReason(), equalTo(GPGVERIFY_ERROR)); } /** - * Creates the signed commit verify error. + * Creates the signed commit unknown signature type. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void createSignedCommitVerifyError() throws IOException { + public void createSignedCommitUnknownSignatureType() throws IOException { GHRepository repository = getRepository(); GHTree ghTree = new GHTreeBuilder(repository).textEntry("a", "", false).create(); GHVerification verification = repository.createCommit() .message("test signing") - .withSignature("-----BEGIN PGP SIGNATURE-----\ninvalid\n-----END PGP SIGNATURE-----") + .withSignature("unknown") .tree(ghTree.getSha()) .create() .getCommitShortInfo() .getVerification(); - assertThat(verification.getReason(), equalTo(GPGVERIFY_ERROR)); + assertThat(verification.getReason(), equalTo(UNKNOWN_SIGNATURE_TYPE)); + } + + /** + * List stargazers. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void listStargazers() throws IOException { + GHRepository repository = getRepository(); + assertThat(repository.listStargazers().toList(), is(empty())); + + repository = gitHub.getOrganization("hub4j").getRepository("github-api"); + Iterable stargazers = repository.listStargazers2(); + GHStargazer stargazer = stargazers.iterator().next(); + assertThat(stargazer.getStarredAt(), equalTo(new Date(1271650383000L))); + assertThat(stargazer.getUser().getLogin(), equalTo("nielswind")); + assertThat(stargazer.getRepository(), sameInstance(repository)); } /** @@ -296,211 +295,220 @@ public void getBranchNonExistentBut200Status() throws Exception { } /** - * Gets the branch URL encoded. + * Subscription. * * @throws Exception * the exception */ @Test - public void getBranch_URLEncoded() throws Exception { - GHRepository repo = getRepository(); - GHBranch branch = repo.getBranch("test/#UrlEncode"); - assertThat(branch.getName(), is("test/#UrlEncode")); + public void subscription() throws Exception { + GHRepository r = getRepository(); + assertThat(r.getSubscription(), nullValue()); + GHSubscription s = r.subscribe(true, false); + try { + + assertThat(r, equalTo(s.getRepository())); + assertThat(s.isIgnored(), equalTo(false)); + assertThat(s.isSubscribed(), equalTo(true)); + assertThat(s.getRepositoryUrl().toString(), containsString("/repos/hub4j-test-org/github-api")); + assertThat(s.getUrl().toString(), containsString("/repos/hub4j-test-org/github-api/subscription")); + + assertThat(s.getReason(), nullValue()); + assertThat(s.getCreatedAt(), equalTo(new Date(1611377286000L))); + } finally { + s.delete(); + } + + assertThat(r.getSubscription(), nullValue()); } /** - * Gets the check runs. + * Test set public. * * @throws Exception * the exception */ @Test - public void getCheckRuns() throws Exception { - final int expectedCount = 8; - // Use github-api repository as it has checks set up - PagedIterable checkRuns = gitHub.getOrganization("hub4j") - .getRepository("github-api") - .getCheckRuns("78b9ff49d47daaa158eb373c4e2e040f739df8b9"); - // Check if the paging works correctly - assertThat(checkRuns.withPageSize(2).iterator().nextPage(), hasSize(2)); - - // Check if the checkruns are all succeeded and if we got all of them - int checkRunsCount = 0; - for (GHCheckRun checkRun : checkRuns) { - assertThat(checkRun.getConclusion(), equalTo(Conclusion.SUCCESS)); - checkRunsCount++; - } - assertThat(checkRunsCount, equalTo(expectedCount)); - - // Check that we can call update on the results - for (GHCheckRun checkRun : checkRuns) { - checkRun.update(); + public void testSetPublic() throws Exception { + kohsuke(); + GHUser myself = gitHub.getMyself(); + String repoName = "test-repo-public"; + GHRepository repo = gitHub.createRepository(repoName).private_(false).create(); + try { + assertThat(repo.isPrivate(), is(false)); + repo.setPrivate(true); + assertThat(myself.getRepository(repoName).isPrivate(), is(true)); + repo.setPrivate(false); + assertThat(myself.getRepository(repoName).isPrivate(), is(false)); + } finally { + repo.delete(); } } /** - * Filter out the checks from a reference + * Tests the creation of repositories with alternating visibilities for orgs. * * @throws Exception * the exception */ @Test - public void getCheckRunsWithParams() throws Exception { - final int expectedCount = 1; - // Use github-api repository as it has checks set up - final Map params = new HashMap<>(1); - params.put("check_name", "build-only (Java 17)"); - PagedIterable checkRuns = gitHub.getOrganization("hub4j") - .getRepository("github-api") - .getCheckRuns("54d60fbb53b4efa19f3081417bfb6a1de30c55e4", params); + public void testCreateVisibilityForOrganization() throws Exception { + GHOrganization organization = gitHub.getOrganization(GITHUB_API_TEST_ORG); - // Check if the checkruns are all succeeded and if we got all of them - int checkRunsCount = 0; - for (GHCheckRun checkRun : checkRuns) { - assertThat(checkRun.getConclusion(), equalTo(Conclusion.SUCCESS)); - checkRunsCount++; + // can not test for internal, as test org is not assigned to an enterprise + for (Visibility visibility : Sets.newHashSet(Visibility.PUBLIC, Visibility.PRIVATE)) { + String repoName = String.format("test-repo-visibility-%s", visibility.toString()); + GHRepository repository = organization.createRepository(repoName).visibility(visibility).create(); + try { + assertThat(repository.getVisibility(), is(visibility)); + assertThat(organization.getRepository(repoName).getVisibility(), is(visibility)); + } finally { + repository.delete(); + } } - assertThat(checkRunsCount, equalTo(expectedCount)); } /** - * Gets the collaborators. + * Tests the creation of repositories with alternating visibilities for users. * * @throws Exception * the exception */ @Test - public void getCollaborators() throws Exception { - GHRepository repo = getRepository(gitHub); - GHPersonSet collaborators = repo.getCollaborators(); - assertThat(collaborators.size(), greaterThan(0)); + public void testCreateVisibilityForUser() throws Exception { + + GHUser myself = gitHub.getMyself(); + + // can not test for internal, as test org is not assigned to an enterprise + for (Visibility visibility : Sets.newHashSet(Visibility.PUBLIC, Visibility.PRIVATE)) { + String repoName = String.format("test-repo-visibility-%s", visibility.toString()); + boolean isPrivate = visibility.equals(Visibility.PRIVATE); + GHRepository repository = gitHub.createRepository(repoName) + .private_(isPrivate) + .visibility(visibility) + .create(); + try { + assertThat(repository.getVisibility(), is(visibility)); + assertThat(myself.getRepository(repoName).getVisibility(), is(visibility)); + } finally { + repository.delete(); + } + } } /** - * Gets the commits between over 250. + * Test update repository. * * @throws Exception * the exception */ @Test - public void getCommitsBetweenOver250() throws Exception { - GHRepository repository = getRepository(); - int startingCount = mockGitHub.getRequestCount(); - GHCompare compare = repository.getCompare("4261c42949915816a9f246eb14c3dfd21a637bc2", - "94ff089e60064bfa43e374baeb10846f7ce82f40"); - int actualCount = 0; - for (GHCompare.Commit item : compare.getCommits()) { - assertThat(item, notNullValue()); - actualCount++; - } - assertThat(compare.getTotalCommits(), is(283)); - assertThat(actualCount, is(250)); - assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 1)); + public void testUpdateRepository() throws Exception { + String homepage = "https://github-api.kohsuke.org/apidocs/index.html"; + String description = "A test repository for update testing via the github-api project"; - // Additional GHCompare checks - assertThat(compare.getAheadBy(), equalTo(283)); - assertThat(compare.getBehindBy(), equalTo(0)); - assertThat(compare.getStatus(), equalTo(GHCompare.Status.ahead)); - assertThat(compare.getDiffUrl().toString(), - endsWith( - "compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40.diff")); - assertThat(compare.getHtmlUrl().toString(), - endsWith( - "compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40")); - assertThat(compare.getPatchUrl().toString(), - endsWith( - "compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40.patch")); - assertThat(compare.getPermalinkUrl().toString(), - endsWith("compare/hub4j-test-org:4261c42...hub4j-test-org:94ff089")); - assertThat(compare.getUrl().toString(), - endsWith( - "compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40")); + GHRepository repo = getTempRepository(); + GHRepository.Updater builder = repo.update(); - assertThat(compare.getBaseCommit().getSHA1(), equalTo("4261c42949915816a9f246eb14c3dfd21a637bc2")); + // one merge option is always required + GHRepository updated = builder.allowRebaseMerge(false) + .allowSquashMerge(false) + .deleteBranchOnMerge(true) + .allowForking(true) + .description(description) + .downloads(false) + .downloads(false) + .homepage(homepage) + .issues(false) + .private_(true) + .projects(false) + .wiki(false) + .done(); - assertThat(compare.getMergeBaseCommit().getSHA1(), equalTo("4261c42949915816a9f246eb14c3dfd21a637bc2")); - // it appears this field is not present in the returned JSON. Strange. - assertThat(compare.getMergeBaseCommit().getCommit().getSha(), nullValue()); - assertThat(compare.getMergeBaseCommit().getCommit().getUrl(), - endsWith("/commits/4261c42949915816a9f246eb14c3dfd21a637bc2")); - assertThat(compare.getMergeBaseCommit().getCommit().getMessage(), - endsWith("[maven-release-plugin] prepare release github-api-1.123")); - assertThat(compare.getMergeBaseCommit().getCommit().getAuthor().getName(), equalTo("Liam Newman")); - assertThat(compare.getMergeBaseCommit().getCommit().getCommitter().getName(), equalTo("Liam Newman")); + assertThat(updated.isAllowMergeCommit(), is(true)); + assertThat(updated.isAllowRebaseMerge(), is(false)); + assertThat(updated.isAllowSquashMerge(), is(false)); + assertThat(updated.isDeleteBranchOnMerge(), is(true)); + assertThat(updated.isAllowForking(), is(true)); + assertThat(updated.isPrivate(), is(true)); + assertThat(updated.hasDownloads(), is(false)); + assertThat(updated.hasIssues(), is(false)); + assertThat(updated.hasProjects(), is(false)); + assertThat(updated.hasWiki(), is(false)); - assertThat(compare.getMergeBaseCommit().getCommit().getTree().getSha(), - equalTo("5da98090976978c93aba0bdfa550e05675543f99")); - assertThat(compare.getMergeBaseCommit().getCommit().getTree().getUrl(), - endsWith("/git/trees/5da98090976978c93aba0bdfa550e05675543f99")); + assertThat(updated.getHomepage(), equalTo(homepage)); + assertThat(updated.getDescription(), equalTo(description)); - assertThat(compare.getFiles().length, equalTo(300)); - assertThat(compare.getFiles()[0].getFileName(), equalTo(".github/PULL_REQUEST_TEMPLATE.md")); - assertThat(compare.getFiles()[0].getLinesAdded(), equalTo(8)); - assertThat(compare.getFiles()[0].getLinesChanged(), equalTo(15)); - assertThat(compare.getFiles()[0].getLinesDeleted(), equalTo(7)); - assertThat(compare.getFiles()[0].getFileName(), equalTo(".github/PULL_REQUEST_TEMPLATE.md")); - assertThat(compare.getFiles()[0].getPatch(), startsWith("@@ -1,15 +1,16 @@")); - assertThat(compare.getFiles()[0].getPreviousFilename(), nullValue()); - assertThat(compare.getFiles()[0].getStatus(), equalTo("modified")); - assertThat(compare.getFiles()[0].getSha(), equalTo("e4234f5f6f39899282a6ef1edff343ae1269222e")); + // test the other merge option and making the repo public again + GHRepository redux = updated.update().allowMergeCommit(false).allowRebaseMerge(true).private_(false).done(); - assertThat(compare.getFiles()[0].getBlobUrl().toString(), - endsWith("/blob/94ff089e60064bfa43e374baeb10846f7ce82f40/.github/PULL_REQUEST_TEMPLATE.md")); - assertThat(compare.getFiles()[0].getRawUrl().toString(), - endsWith("/raw/94ff089e60064bfa43e374baeb10846f7ce82f40/.github/PULL_REQUEST_TEMPLATE.md")); + assertThat(redux.isAllowMergeCommit(), is(false)); + assertThat(redux.isAllowRebaseMerge(), is(true)); + assertThat(redux.isPrivate(), is(false)); + + String updatedDescription = "updated using set()"; + redux = redux.set().description(updatedDescription); + + assertThat(redux.getDescription(), equalTo(updatedDescription)); } /** - * Gets the commits between paged. + * Test get repository with visibility. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void getCommitsBetweenPaged() throws Exception { - GHRepository repository = getRepository(); - int startingCount = mockGitHub.getRequestCount(); - repository.setCompareUsePaginatedCommits(true); - GHCompare compare = repository.getCompare("4261c42949915816a9f246eb14c3dfd21a637bc2", - "94ff089e60064bfa43e374baeb10846f7ce82f40"); - int actualCount = 0; - for (GHCompare.Commit item : compare.getCommits()) { - assertThat(item, notNullValue()); - actualCount++; - } - assertThat(compare.getTotalCommits(), is(283)); - assertThat(actualCount, is(283)); - assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 4)); + public void testGetRepositoryWithVisibility() throws IOException { + snapshotNotAllowed(); + final String repoName = "test-repo-visibility"; + final GHRepository repo = getTempRepository(repoName); + assertThat(repo.getVisibility(), equalTo(Visibility.PUBLIC)); + + repo.setVisibility(Visibility.INTERNAL); + assertThat(gitHub.getRepository(repo.getOwnerName() + "/" + repo.getName()).getVisibility(), + equalTo(Visibility.INTERNAL)); + + repo.setVisibility(Visibility.PRIVATE); + assertThat(gitHub.getRepository(repo.getOwnerName() + "/" + repo.getName()).getVisibility(), + equalTo(Visibility.PRIVATE)); + + repo.setVisibility(Visibility.PUBLIC); + assertThat(gitHub.getRepository(repo.getOwnerName() + "/" + repo.getName()).getVisibility(), + equalTo(Visibility.PUBLIC)); + + // deliberately bogus response in snapshot + assertThat(gitHub.getRepository(repo.getOwnerName() + "/" + repo.getName()).getVisibility(), + equalTo(Visibility.UNKNOWN)); } /** - * Gets the delete branch on merge. + * List contributors. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void getDeleteBranchOnMerge() throws IOException { - GHRepository r = getRepository(); - assertThat(r.isDeleteBranchOnMerge(), notNullValue()); + public void listContributors() throws IOException { + GHRepository r = gitHub.getOrganization("hub4j").getRepository("github-api"); + int i = 0; + boolean kohsuke = false; + + for (GHRepository.Contributor c : r.listContributors()) { + if (c.getLogin().equals("kohsuke")) { + assertThat(c.getContributions(), greaterThan(0)); + kohsuke = true; + } + if (i++ > 5) { + break; + } + } + + assertThat(kohsuke, is(true)); } /** - * Gets the last commit status. - * - * @throws Exception - * the exception - */ - @Test - public void getLastCommitStatus() throws Exception { - GHCommitStatus status = getRepository().getLastCommitStatus("8051615eff597f4e49f4f47625e6fc2b49f26bfc"); - assertThat(status.getId(), equalTo(9027542286L)); - assertThat(status.getState(), equalTo(GHCommitState.SUCCESS)); - assertThat(status.getContext(), equalTo("ci/circleci: build")); - } - - /** - * Gets the permission. + * Gets the permission. * * @throws Exception * the exception @@ -534,143 +542,145 @@ public void getPermission() throws Exception { } /** - * Gets the post commit hooks. + * Checks for permission. * * @throws Exception * the exception */ @Test - public void getPostCommitHooks() throws Exception { - GHRepository repo = getRepository(gitHub); - Set postcommitHooks = setupPostCommitHooks(repo); - assertThat(postcommitHooks, is(empty())); + public void hasPermission() throws Exception { + kohsuke(); + GHRepository publicRepository = gitHub.getRepository("hub4j-test-org/test-permission"); + assertThat(publicRepository.hasPermission("kohsuke", GHPermissionType.ADMIN), equalTo(true)); + assertThat(publicRepository.hasPermission("kohsuke", GHPermissionType.WRITE), equalTo(true)); + assertThat(publicRepository.hasPermission("kohsuke", GHPermissionType.READ), equalTo(true)); + assertThat(publicRepository.hasPermission("kohsuke", GHPermissionType.NONE), equalTo(false)); + + assertThat(publicRepository.hasPermission("dude", GHPermissionType.ADMIN), equalTo(false)); + assertThat(publicRepository.hasPermission("dude", GHPermissionType.WRITE), equalTo(false)); + assertThat(publicRepository.hasPermission("dude", GHPermissionType.READ), equalTo(true)); + assertThat(publicRepository.hasPermission("dude", GHPermissionType.NONE), equalTo(false)); + + // also check the GHUser method + GHUser kohsuke = gitHub.getUser("kohsuke"); + assertThat(publicRepository.hasPermission(kohsuke, GHPermissionType.ADMIN), equalTo(true)); + assertThat(publicRepository.hasPermission(kohsuke, GHPermissionType.WRITE), equalTo(true)); + assertThat(publicRepository.hasPermission(kohsuke, GHPermissionType.READ), equalTo(true)); + assertThat(publicRepository.hasPermission(kohsuke, GHPermissionType.NONE), equalTo(false)); + + // check NONE on a private project + GHRepository privateRepository = gitHub.getRepository("hub4j-test-org/test-permission-private"); + assertThat(privateRepository.hasPermission("dude", GHPermissionType.ADMIN), equalTo(false)); + assertThat(privateRepository.hasPermission("dude", GHPermissionType.WRITE), equalTo(false)); + assertThat(privateRepository.hasPermission("dude", GHPermissionType.READ), equalTo(false)); + assertThat(privateRepository.hasPermission("dude", GHPermissionType.NONE), equalTo(true)); } /** - * Gets the public key. - * - * @throws Exception - * the exception + * Latest repository exist. */ @Test - public void getPublicKey() throws Exception { - GHRepository repo = getTempRepository(); - GHRepositoryPublicKey publicKey = repo.getPublicKey(); - assertThat(publicKey, notNullValue()); - assertThat(publicKey.getKey(), equalTo("test-key")); - assertThat(publicKey.getKeyId(), equalTo("key-id")); + public void LatestRepositoryExist() { + try { + // add the repository that have latest release + GHRelease release = gitHub.getRepository("kamontat/CheckIDNumber").getLatestRelease(); + assertThat(release.getTagName(), equalTo("v3.0")); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } } /** - * Gets the ref. + * Adds the collaborators. * * @throws Exception * the exception */ @Test - public void getRef() throws Exception { + public void addCollaborators() throws Exception { GHRepository repo = getRepository(); + GHUser user = getUser(); + List users = new ArrayList<>(); - GHRef ghRef; - - // handle refs/* - ghRef = repo.getRef("heads/gh-pages"); - GHRef ghRefWithPrefix = repo.getRef("refs/heads/gh-pages"); - - assertThat(ghRef, notNullValue()); - assertThat(ghRef.getRef(), equalTo("refs/heads/gh-pages")); - assertThat(ghRefWithPrefix.getRef(), equalTo(ghRef.getRef())); - assertThat(ghRefWithPrefix.getObject().getType(), equalTo("commit")); - assertThat(ghRefWithPrefix.getObject().getUrl().toString(), - containsString("/repos/hub4j-test-org/github-api/git/commits/")); - - // git/refs/heads/gh-pages - ghRef = repo.getRef("heads/gh-pages"); - assertThat(ghRef, notNullValue()); - assertThat(ghRef.getRef(), equalTo("refs/heads/gh-pages")); + users.add(user); + users.add(gitHub.getUser("jimmysombrero2")); + repo.addCollaborators(users, RepositoryRole.from(GHOrganization.Permission.PUSH)); - // git/refs/heads/gh - try { - ghRef = repo.getRef("heads/gh"); - fail(); - } catch (Exception e) { - assertThat(e, instanceOf(GHFileNotFoundException.class)); - assertThat(e.getMessage(), - containsString( - "{\"message\":\"Not Found\",\"documentation_url\":\"https://developer.github.com/v3/git/refs/#get-a-reference\"}")); - } + GHPersonSet collabs = repo.getCollaborators(); + GHUser colabUser = collabs.byLogin("jimmysombrero"); - // git/refs/headz - try { - ghRef = repo.getRef("headz"); - fail(); - } catch (Exception e) { - assertThat(e, instanceOf(GHFileNotFoundException.class)); - assertThat(e.getMessage(), - containsString( - "{\"message\":\"Not Found\",\"documentation_url\":\"https://developer.github.com/v3/git/refs/#get-a-reference\"}")); - } + assertThat(user.getName(), equalTo(colabUser.getName())); } /** - * Gets the refs. + * Adds the collaborators repo perm. * * @throws Exception * the exception */ @Test - public void getRefs() throws Exception { - GHRepository repo = getTempRepository(); - GHRef[] refs = repo.getRefs(); - assertThat(refs, notNullValue()); - assertThat(refs.length, equalTo(1)); - assertThat(refs[0].getRef(), equalTo("refs/heads/main")); + public void addCollaboratorsRepoPerm() throws Exception { + GHRepository repo = getRepository(); + GHUser user = getUser(); + + RepositoryRole role = RepositoryRole.from(GHOrganization.Permission.PULL); + repo.addCollaborators(role, user); + + GHPersonSet collabs = repo.getCollaborators(); + GHUser colabUser = collabs.byLogin("jgangemi"); + + assertThat(user.getName(), equalTo(colabUser.getName())); } /** - * Gets the refs empty tags. - * - * @throws Exception - * the exception + * Latest repository not exist. */ @Test - public void getRefsEmptyTags() throws Exception { - GHRepository repo = getTempRepository(); + public void LatestRepositoryNotExist() { try { - repo.getRefs("tags"); + // add the repository that `NOT` have latest release + GHRelease release = gitHub.getRepository("kamontat/Java8Example").getLatestRelease(); + assertThat(release, nullValue()); + } catch (IOException e) { + e.printStackTrace(); fail(); - } catch (Exception e) { - assertThat(e, instanceOf(GHFileNotFoundException.class)); - assertThat(e.getMessage(), - containsString( - "{\"message\":\"Not Found\",\"documentation_url\":\"https://developer.github.com/v3/git/refs/#get-a-reference\"}")); } } /** - * Gets the refs heads. + * List releases. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void getRefsHeads() throws Exception { - GHRepository repo = getTempRepository(); - GHRef[] refs = repo.getRefs("heads"); - assertThat(refs, notNullValue()); - assertThat(refs.length, equalTo(1)); - assertThat(refs[0].getRef(), equalTo("refs/heads/main")); + public void listReleases() throws IOException { + PagedIterable releases = gitHub.getOrganization("github").getRepository("hub").listReleases(); + assertThat(releases, is(not(emptyIterable()))); } /** - * Gets the release by tag name does not exist. + * Gets the release exists. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void getReleaseByTagNameDoesNotExist() throws IOException { - GHRelease release = getRepository().getReleaseByTagName("foo-bar-baz"); + public void getReleaseExists() throws IOException { + GHRelease release = gitHub.getOrganization("github").getRepository("hub").getRelease(6839710); + assertThat(release.getTagName(), equalTo("v2.3.0-pre10")); + } + + /** + * Gets the release does not exist. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void getReleaseDoesNotExist() throws IOException { + GHRelease release = gitHub.getOrganization("github").getRepository("hub").getRelease(Long.MAX_VALUE); assertThat(release, nullValue()); } @@ -688,176 +698,129 @@ public void getReleaseByTagNameExists() throws IOException { } /** - * Gets the release does not exist. + * Gets the release by tag name does not exist. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void getReleaseDoesNotExist() throws IOException { - GHRelease release = gitHub.getOrganization("github").getRepository("hub").getRelease(Long.MAX_VALUE); + public void getReleaseByTagNameDoesNotExist() throws IOException { + GHRelease release = getRepository().getReleaseByTagName("foo-bar-baz"); assertThat(release, nullValue()); } /** - * Gets the release exists. + * List languages. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void getReleaseExists() throws IOException { - GHRelease release = gitHub.getOrganization("github").getRepository("hub").getRelease(6839710); - assertThat(release.getTagName(), equalTo("v2.3.0-pre10")); + public void listLanguages() throws IOException { + GHRepository r = gitHub.getRepository("hub4j/github-api"); + String mainLanguage = r.getLanguage(); + assertThat(mainLanguage, equalTo("Java")); + Map languages = r.listLanguages(); + assertThat(languages.containsKey(mainLanguage), is(true)); + assertThat(languages.get("Java"), greaterThan(100000L)); } /** - * Gh repository search builder fork default reset forks search terms. + * List commit comments no comments. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void ghRepositorySearchBuilderForkDefaultResetForksSearchTerms() { - GHRepositorySearchBuilder ghRepositorySearchBuilder = new GHRepositorySearchBuilder(gitHub); + public void listCommitCommentsNoComments() throws IOException { + List commitComments = getRepository() + .listCommitComments("c413fc1e3057332b93850ea48202627d29a37de5") + .toList(); - ghRepositorySearchBuilder = ghRepositorySearchBuilder.fork(GHFork.PARENT_AND_FORKS); - assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:true")).count(), is(1L)); - assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:")).count(), is(1L)); + assertThat("Commit has no comments", commitComments.isEmpty()); - ghRepositorySearchBuilder = ghRepositorySearchBuilder.fork(GHFork.FORKS_ONLY); - assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:only")).count(), is(1L)); - assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:")).count(), is(2L)); + commitComments = getRepository().getCommit("c413fc1e3057332b93850ea48202627d29a37de5").listComments().toList(); - ghRepositorySearchBuilder = ghRepositorySearchBuilder.fork(GHFork.PARENT_ONLY); - assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:")).count(), is(0L)); + assertThat("Commit has no comments", commitComments.isEmpty()); } /** - * Gh repository search builder ignores unknown visibility. + * Search all public and forked repos. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void ghRepositorySearchBuilderIgnoresUnknownVisibility() { - GHRepositorySearchBuilder ghRepositorySearchBuilder; - - GHException exception = assertThrows(GHException.class, - () -> new GHRepositorySearchBuilder(gitHub).visibility(Visibility.UNKNOWN)); - assertThat(exception.getMessage(), - startsWith("UNKNOWN is a placeholder for unexpected values encountered when reading data.")); - - ghRepositorySearchBuilder = new GHRepositorySearchBuilder(gitHub).visibility(Visibility.PUBLIC); - assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("is:")).count(), is(1L)); - - ghRepositorySearchBuilder = new GHRepositorySearchBuilder(gitHub).visibility(Visibility.PRIVATE); - assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("is:")).count(), is(1L)); - - ghRepositorySearchBuilder = new GHRepositorySearchBuilder(gitHub).visibility(Visibility.INTERNAL); - assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("is:")).count(), is(1L)); + public void searchAllPublicAndForkedRepos() throws IOException { + PagedSearchIterable list = gitHub.searchRepositories() + .user("t0m4uk1991") + .visibility(GHRepository.Visibility.PUBLIC) + .fork(GHFork.PARENT_AND_FORKS) + .list(); + List u = list.toList(); + assertThat(u.size(), is(14)); + assertThat(u.stream().filter(item -> item.getName().equals("github-api")).count(), is(1L)); + assertThat(u.stream().filter(item -> item.getName().equals("Complete-Python-3-Bootcamp")).count(), is(1L)); } /** - * Checks for permission. + * Search for public forked only repos. * - * @throws Exception - * the exception - */ - @Test - public void hasPermission() throws Exception { - kohsuke(); - GHRepository publicRepository = gitHub.getRepository("hub4j-test-org/test-permission"); - assertThat(publicRepository.hasPermission("kohsuke", GHPermissionType.ADMIN), equalTo(true)); - assertThat(publicRepository.hasPermission("kohsuke", GHPermissionType.WRITE), equalTo(true)); - assertThat(publicRepository.hasPermission("kohsuke", GHPermissionType.READ), equalTo(true)); - assertThat(publicRepository.hasPermission("kohsuke", GHPermissionType.NONE), equalTo(false)); - - assertThat(publicRepository.hasPermission("dude", GHPermissionType.ADMIN), equalTo(false)); - assertThat(publicRepository.hasPermission("dude", GHPermissionType.WRITE), equalTo(false)); - assertThat(publicRepository.hasPermission("dude", GHPermissionType.READ), equalTo(true)); - assertThat(publicRepository.hasPermission("dude", GHPermissionType.NONE), equalTo(false)); - - // also check the GHUser method - GHUser kohsuke = gitHub.getUser("kohsuke"); - assertThat(publicRepository.hasPermission(kohsuke, GHPermissionType.ADMIN), equalTo(true)); - assertThat(publicRepository.hasPermission(kohsuke, GHPermissionType.WRITE), equalTo(true)); - assertThat(publicRepository.hasPermission(kohsuke, GHPermissionType.READ), equalTo(true)); - assertThat(publicRepository.hasPermission(kohsuke, GHPermissionType.NONE), equalTo(false)); - - // check NONE on a private project - GHRepository privateRepository = gitHub.getRepository("hub4j-test-org/test-permission-private"); - assertThat(privateRepository.hasPermission("dude", GHPermissionType.ADMIN), equalTo(false)); - assertThat(privateRepository.hasPermission("dude", GHPermissionType.WRITE), equalTo(false)); - assertThat(privateRepository.hasPermission("dude", GHPermissionType.READ), equalTo(false)); - assertThat(privateRepository.hasPermission("dude", GHPermissionType.NONE), equalTo(true)); - } - - /** - * Checks if is disabled. - * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void isDisabled() throws Exception { - GHRepository r = getRepository(); - - assertThat(r.isDisabled(), is(false)); + public void searchForPublicForkedOnlyRepos() throws IOException { + PagedSearchIterable list = gitHub.searchRepositories() + .user("t0m4uk1991") + .visibility(GHRepository.Visibility.PUBLIC) + .fork(GHFork.FORKS_ONLY) + .list(); + List u = list.toList(); + assertThat(u.size(), is(2)); + assertThat(u.get(0).getName(), is("github-api")); + assertThat(u.get(1).getName(), is("Complete-Python-3-Bootcamp")); } /** - * Checks if is disabled true. - * - * @throws Exception - * the exception + * Gh repository search builder ignores unknown visibility. */ @Test - public void isDisabledTrue() throws Exception { - GHRepository r = getRepository(); + public void ghRepositorySearchBuilderIgnoresUnknownVisibility() { + GHRepositorySearchBuilder ghRepositorySearchBuilder; - assertThat(r.isDisabled(), is(true)); - } + GHException exception = assertThrows(GHException.class, + () -> new GHRepositorySearchBuilder(gitHub).visibility(Visibility.UNKNOWN)); + assertThat(exception.getMessage(), + startsWith("UNKNOWN is a placeholder for unexpected values encountered when reading data.")); - /** - * List collaborators. - * - * @throws Exception - * the exception - */ - @Test - public void listCollaborators() throws Exception { - GHRepository repo = getRepository(); - List collaborators = repo.listCollaborators().toList(); - assertThat(collaborators.size(), greaterThan(10)); - } + ghRepositorySearchBuilder = new GHRepositorySearchBuilder(gitHub).visibility(Visibility.PUBLIC); + assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("is:")).count(), is(1L)); - /** - * List collaborators filtered. - * - * @throws Exception - * the exception - */ - @Test - public void listCollaboratorsFiltered() throws Exception { - GHRepository repo = getRepository(); - List allCollaborators = repo.listCollaborators().toList(); - List filteredCollaborators = repo.listCollaborators(GHRepository.CollaboratorAffiliation.OUTSIDE) - .toList(); - assertThat(filteredCollaborators.size(), lessThan(allCollaborators.size())); + ghRepositorySearchBuilder = new GHRepositorySearchBuilder(gitHub).visibility(Visibility.PRIVATE); + assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("is:")).count(), is(1L)); + + ghRepositorySearchBuilder = new GHRepositorySearchBuilder(gitHub).visibility(Visibility.INTERNAL); + assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("is:")).count(), is(1L)); } /** - * List commit comments no comments. - * - * @throws IOException - * Signals that an I/O exception has occurred. + * Gh repository search builder fork default reset forks search terms. */ @Test - public void listCommitCommentsNoComments() throws IOException { - List commitComments = getRepository() - .listCommitComments("c413fc1e3057332b93850ea48202627d29a37de5") - .toList(); + public void ghRepositorySearchBuilderForkDefaultResetForksSearchTerms() { + GHRepositorySearchBuilder ghRepositorySearchBuilder = new GHRepositorySearchBuilder(gitHub); - assertThat("Commit has no comments", commitComments.isEmpty()); + ghRepositorySearchBuilder = ghRepositorySearchBuilder.fork(GHFork.PARENT_AND_FORKS); + assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:true")).count(), is(1L)); + assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:")).count(), is(1L)); - commitComments = getRepository().getCommit("c413fc1e3057332b93850ea48202627d29a37de5").listComments().toList(); + ghRepositorySearchBuilder = ghRepositorySearchBuilder.fork(GHFork.FORKS_ONLY); + assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:only")).count(), is(1L)); + assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:")).count(), is(2L)); - assertThat("Commit has no comments", commitComments.isEmpty()); + ghRepositorySearchBuilder = ghRepositorySearchBuilder.fork(GHFork.PARENT_ONLY); + assertThat(ghRepositorySearchBuilder.terms.stream().filter(item -> item.contains("fork:")).count(), is(0L)); } /** @@ -886,742 +849,919 @@ public void listCommitCommentsSomeComments() throws IOException { } /** - * List commits between. + * List empty contributors. * - * @throws Exception - * the exception + * @throws IOException + * Signals that an I/O exception has occurred. */ - @Test - public void listCommitsBetween() throws Exception { - GHRepository repository = getRepository(); - int startingCount = mockGitHub.getRequestCount(); - GHCompare compare = repository.getCompare("e46a9f3f2ac55db96de3c5c4706f2813b3a96465", - "8051615eff597f4e49f4f47625e6fc2b49f26bfc"); - int actualCount = 0; - for (GHCompare.Commit item : compare.listCommits().withPageSize(5)) { - assertThat(item, notNullValue()); - actualCount++; - } - assertThat(compare.getTotalCommits(), is(9)); - assertThat(actualCount, is(9)); - assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 1)); + @Test // Issue #261 + public void listEmptyContributors() throws IOException { + assertThat("This list should be empty, but should return a valid empty iterable.", + gitHub.getRepository(GITHUB_API_TEST_ORG + "/empty").listContributors(), + is(emptyIterable())); } /** - * List commits between paginated. + * Search repositories. * * @throws Exception * the exception */ @Test - public void listCommitsBetweenPaginated() throws Exception { - GHRepository repository = getRepository(); - int startingCount = mockGitHub.getRequestCount(); - repository.setCompareUsePaginatedCommits(true); - GHCompare compare = repository.getCompare("e46a9f3f2ac55db96de3c5c4706f2813b3a96465", - "8051615eff597f4e49f4f47625e6fc2b49f26bfc"); - int actualCount = 0; - for (GHCompare.Commit item : compare.listCommits().withPageSize(5)) { - assertThat(item, notNullValue()); - actualCount++; - } - assertThat(compare.getTotalCommits(), is(9)); - assertThat(actualCount, is(9)); - assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 3)); + public void searchRepositories() throws Exception { + PagedSearchIterable r = gitHub.searchRepositories() + .q("tetris") + .language("assembly") + .sort(GHRepositorySearchBuilder.Sort.STARS) + .list(); + GHRepository u = r.iterator().next(); + // System.out.println(u.getName()); + assertThat(u.getId(), notNullValue()); + assertThat(u.getLanguage(), equalTo("Assembly")); + assertThat(r.getTotalCount(), greaterThan(0)); } /** - * List contributors. + * Search org for repositories. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void listContributors() throws IOException { - GHRepository r = gitHub.getOrganization("hub4j").getRepository("github-api"); - int i = 0; - boolean kohsuke = false; - - for (GHRepository.Contributor c : r.listContributors()) { - if (c.getLogin().equals("kohsuke")) { - assertThat(c.getContributions(), greaterThan(0)); - kohsuke = true; - } - if (i++ > 5) { - break; - } - } - - assertThat(kohsuke, is(true)); + public void searchOrgForRepositories() throws Exception { + PagedSearchIterable r = gitHub.searchRepositories().org("hub4j-test-org").list(); + GHRepository u = r.iterator().next(); + assertThat(u.getOwnerName(), equalTo("hub4j-test-org")); + assertThat(r.getTotalCount(), greaterThan(0)); } /** - * List contributors. + * Test issue 162. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ - @Test - public void listContributorsAnon() throws IOException { - GHRepository r = gitHub.getOrganization("hub4j").getRepository("github-api"); - int i = 0; - boolean kohsuke = false; - - for (GHRepository.Contributor c : r.listContributors(true)) { - if (c.getType().equals("Anonymous")) { - assertThat(c.getContributions(), is(3)); - kohsuke = true; - } - if (++i > 1) { - break; + @Test // issue #162 + public void testIssue162() throws Exception { + GHRepository r = gitHub.getRepository("hub4j/github-api"); + List contents = r.getDirectoryContent("", "gh-pages"); + for (GHContent content : contents) { + if (content.isFile()) { + String content1 = content.getContent(); + String content2 = r.getFileContent(content.getPath(), "gh-pages").getContent(); + // System.out.println(content.getPath()); + assertThat(content2, equalTo(content1)); } } - - assertThat(kohsuke, is(true)); } /** - * List empty contributors. + * Mark down. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ - @Test // Issue #261 - public void listEmptyContributors() throws IOException { - assertThat("This list should be empty, but should return a valid empty iterable.", - gitHub.getRepository(GITHUB_API_TEST_ORG + "/empty").listContributors(), - is(emptyIterable())); + @Test + public void markDown() throws Exception { + assertThat(IOUtils.toString(gitHub.renderMarkdown("**Test日本語**")).trim(), + equalTo("

Test日本語

")); + + String actual = IOUtils.toString( + gitHub.getRepository("hub4j/github-api").renderMarkdown("@kohsuke to fix issue #1", MarkdownMode.GFM)); + // System.out.println(actual); + assertThat(actual, containsString("href=\"https://github.com/kohsuke\"")); + assertThat(actual, containsString("href=\"https://github.com/hub4j/github-api/pull/1\"")); + assertThat(actual, containsString("class=\"user-mention\"")); + assertThat(actual, containsString("class=\"issue-link ")); + assertThat(actual, containsString("to fix issue")); } /** - * List languages. + * Sets the merge options. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void listLanguages() throws IOException { - GHRepository r = gitHub.getRepository("hub4j/github-api"); - String mainLanguage = r.getLanguage(); - assertThat(mainLanguage, equalTo("Java")); - Map languages = r.listLanguages(); - assertThat(languages.containsKey(mainLanguage), is(true)); - assertThat(languages.get("Java"), greaterThan(100000L)); - } - - /** - * List refs. - * - * @throws Exception - * the exception - */ - @Test - public void listRefs() throws Exception { - GHRepository repo = getRepository(); + public void setMergeOptions() throws IOException { + // String repoName = "hub4j-test-org/test-mergeoptions"; + GHRepository r = getTempRepository(); - List ghRefs; + // at least one merge option must be selected + // flip all the values at least once + r.allowSquashMerge(true); - // handle refs/* - ghRefs = repo.listRefs("heads").toList(); - List ghRefsWithPrefix = repo.listRefs("refs/heads").toList(); + r.allowMergeCommit(false); + r.allowRebaseMerge(false); - assertThat(ghRefs, notNullValue()); - assertThat(ghRefs.size(), greaterThan(3)); - assertThat(ghRefs.get(0).getRef(), equalTo("refs/heads/changes")); - assertThat(ghRefsWithPrefix.size(), equalTo(ghRefs.size())); - assertThat(ghRefsWithPrefix.get(0).getRef(), equalTo(ghRefs.get(0).getRef())); + r = gitHub.getRepository(r.getFullName()); + assertThat(r.isAllowMergeCommit(), is(false)); + assertThat(r.isAllowRebaseMerge(), is(false)); + assertThat(r.isAllowSquashMerge(), is(true)); - // git/refs/heads/gh-pages - // passing a specific ref to listRefs will fail to parse due to returning a - // single item not an array - try { - ghRefs = repo.listRefs("heads/gh-pages").toList(); - fail(); - } catch (Exception e) { - assertThat(e, instanceOf(HttpException.class)); - assertThat(e.getCause(), instanceOf(JsonMappingException.class)); - } + // flip the last value + r.allowMergeCommit(true); + r.allowRebaseMerge(true); + r.allowSquashMerge(false); - // git/refs/heads/gh - ghRefs = repo.listRefs("heads/gh").toList(); - assertThat(ghRefs, notNullValue()); - assertThat(ghRefs.size(), equalTo(1)); - assertThat(ghRefs.get(0).getRef(), equalTo("refs/heads/gh-pages")); + r = gitHub.getRepository(r.getFullName()); + assertThat(r.isAllowMergeCommit(), is(true)); + assertThat(r.isAllowRebaseMerge(), is(true)); + assertThat(r.isAllowSquashMerge(), is(false)); + } - // git/refs/headz - try { - ghRefs = repo.listRefs("headz").toList(); - fail(); - } catch (Exception e) { - assertThat(e, instanceOf(GHFileNotFoundException.class)); - assertThat(e.getMessage(), - containsString( - "{\"message\":\"Not Found\",\"documentation_url\":\"https://developer.github.com/v3/git/refs/#get-a-reference\"}")); - } + /** + * Gets the delete branch on merge. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void getDeleteBranchOnMerge() throws IOException { + GHRepository r = getRepository(); + assertThat(r.isDeleteBranchOnMerge(), notNullValue()); } /** - * List refs empty tags. + * Sets the delete branch on merge. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void listRefsEmptyTags() { - try { - GHRepository repo = getTempRepository(); - repo.listRefs("tags").toList(); - fail(); - } catch (Exception e) { - assertThat(e, instanceOf(GHFileNotFoundException.class)); - assertThat(e.getMessage(), containsString("/repos/hub4j-test-org/temp-listRefsEmptyTags/git/refs/tags")); - } + public void setDeleteBranchOnMerge() throws IOException { + GHRepository r = getRepository(); + + // enable auto delete + r.deleteBranchOnMerge(true); + + r = gitHub.getRepository(r.getFullName()); + assertThat(r.isDeleteBranchOnMerge(), is(true)); + + // flip the last value + r.deleteBranchOnMerge(false); + + r = gitHub.getRepository(r.getFullName()); + assertThat(r.isDeleteBranchOnMerge(), is(false)); } /** - * List refs heads. + * Test set topics. * * @throws Exception * the exception */ @Test - public void listRefsHeads() throws Exception { - GHRepository repo = getTempRepository(); - List refs = repo.listRefs("heads").toList(); - assertThat(refs, notNullValue()); - assertThat(refs.size(), equalTo(1)); - assertThat(refs.get(0).getRef(), equalTo("refs/heads/main")); + public void testSetTopics() throws Exception { + GHRepository repo = getRepository(gitHub); + + List topics = new ArrayList<>(); + + topics.add("java"); + topics.add("api-test-dummy"); + repo.setTopics(topics); + assertThat("Topics retain input order (are not sort when stored)", + repo.listTopics(), + contains("java", "api-test-dummy")); + + topics = new ArrayList<>(); + topics.add("ordered-state"); + topics.add("api-test-dummy"); + topics.add("java"); + repo.setTopics(topics); + assertThat("Topics behave as a set and retain order from previous calls", + repo.listTopics(), + contains("java", "api-test-dummy", "ordered-state")); + + topics = new ArrayList<>(); + topics.add("ordered-state"); + topics.add("api-test-dummy"); + repo.setTopics(topics); + assertThat("Topics retain order even when some are removed", + repo.listTopics(), + contains("api-test-dummy", "ordered-state")); + + topics = new ArrayList<>(); + repo.setTopics(topics); + assertThat("Topics can be set to empty", repo.listTopics(), is(empty())); } /** - * List releases. + * Gets the collaborators. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void listReleases() throws IOException { - PagedIterable releases = gitHub.getOrganization("github").getRepository("hub").listReleases(); - assertThat(releases, is(not(emptyIterable()))); + public void getCollaborators() throws Exception { + GHRepository repo = getRepository(gitHub); + GHPersonSet collaborators = repo.getCollaborators(); + assertThat(collaborators.size(), greaterThan(0)); } /** - * List stargazers. + * Gets the post commit hooks. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void listStargazers() throws IOException { - GHRepository repository = getRepository(); - assertThat(repository.listStargazers().toList(), is(empty())); + public void getPostCommitHooks() throws Exception { + GHRepository repo = getRepository(gitHub); + Set postcommitHooks = setupPostCommitHooks(repo); + assertThat(postcommitHooks, is(empty())); + } - repository = gitHub.getOrganization("hub4j").getRepository("github-api"); - Iterable stargazers = repository.listStargazers2(); - GHStargazer stargazer = stargazers.iterator().next(); - assertThat(stargazer.getStarredAt(), equalTo(Instant.ofEpochMilli(1271650383000L))); - assertThat(stargazer.getUser().getLogin(), equalTo("nielswind")); - assertThat(stargazer.getRepository(), sameInstance(repository)); + @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", + justification = "It causes a performance degradation, but we have already exposed it to the API") + private Set setupPostCommitHooks(final GHRepository repo) { + return new AbstractSet() { + private List getPostCommitHooks() { + try { + List r = new ArrayList<>(); + for (GHHook h : repo.getHooks()) { + if (h.getName().equals("web")) { + r.add(new URL(h.getConfig().get("url"))); + } + } + return r; + } catch (IOException e) { + throw new GHException("Failed to retrieve post-commit hooks", e); + } + } + + @Override + public Iterator iterator() { + return getPostCommitHooks().iterator(); + } + + @Override + public int size() { + return getPostCommitHooks().size(); + } + + @Override + public boolean add(URL url) { + try { + repo.createWebHook(url); + return true; + } catch (IOException e) { + throw new GHException("Failed to update post-commit hooks", e); + } + } + + @Override + public boolean remove(Object url) { + try { + String _url = ((URL) url).toExternalForm(); + for (GHHook h : repo.getHooks()) { + if (h.getName().equals("web") && h.getConfig().get("url").equals(_url)) { + h.delete(); + return true; + } + } + return false; + } catch (IOException e) { + throw new GHException("Failed to update post-commit hooks", e); + } + } + }; } /** - * List tags. + * Gets the refs. * * @throws Exception * the exception */ @Test - public void listTags() throws Exception { - GHRepository repo = getRepository(); - List refs = repo.listTags().withPageSize(33).toList(); + public void getRefs() throws Exception { + GHRepository repo = getTempRepository(); + GHRef[] refs = repo.getRefs(); assertThat(refs, notNullValue()); - assertThat(refs.size(), greaterThan(90)); + assertThat(refs.length, equalTo(1)); + assertThat(refs[0].getRef(), equalTo("refs/heads/main")); } /** - * List tags empty. + * Gets the public key. * * @throws Exception * the exception */ @Test - public void listTagsEmpty() throws Exception { + public void getPublicKey() throws Exception { GHRepository repo = getTempRepository(); - List refs = repo.listTags().toList(); - assertThat(refs, notNullValue()); - assertThat(refs, is(empty())); + GHRepositoryPublicKey publicKey = repo.getPublicKey(); + assertThat(publicKey, notNullValue()); + assertThat(publicKey.getKey(), equalTo("test-key")); + assertThat(publicKey.getKeyId(), equalTo("key-id")); } /** - * Mark down. + * Gets the refs heads. * * @throws Exception * the exception */ @Test - public void markDown() throws Exception { - assertThat(IOUtils.toString(gitHub.renderMarkdown("**Test日本語**")).trim(), - equalTo("

Test日本語

")); - - String actual = IOUtils.toString( - gitHub.getRepository("hub4j/github-api").renderMarkdown("@kohsuke to fix issue #1", MarkdownMode.GFM)); - // System.out.println(actual); - assertThat(actual, containsString("href=\"https://github.com/kohsuke\"")); - assertThat(actual, containsString("href=\"https://github.com/hub4j/github-api/pull/1\"")); - assertThat(actual, containsString("class=\"user-mention\"")); - assertThat(actual, containsString("class=\"issue-link ")); - assertThat(actual, containsString("to fix issue")); + public void getRefsHeads() throws Exception { + GHRepository repo = getTempRepository(); + GHRef[] refs = repo.getRefs("heads"); + assertThat(refs, notNullValue()); + assertThat(refs.length, equalTo(1)); + assertThat(refs[0].getRef(), equalTo("refs/heads/main")); } /** - * Search all public and forked repos. + * Gets the refs empty tags. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void searchAllPublicAndForkedRepos() throws IOException { - PagedSearchIterable list = gitHub.searchRepositories() - .user("t0m4uk1991") - .visibility(GHRepository.Visibility.PUBLIC) - .fork(GHFork.PARENT_AND_FORKS) - .list(); - List u = list.toList(); - assertThat(u.size(), is(14)); - assertThat(u.stream().filter(item -> item.getName().equals("github-api")).count(), is(1L)); - assertThat(u.stream().filter(item -> item.getName().equals("Complete-Python-3-Bootcamp")).count(), is(1L)); + public void getRefsEmptyTags() throws Exception { + GHRepository repo = getTempRepository(); + try { + repo.getRefs("tags"); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(GHFileNotFoundException.class)); + assertThat(e.getMessage(), + containsString( + "{\"message\":\"Not Found\",\"documentation_url\":\"https://developer.github.com/v3/git/refs/#get-a-reference\"}")); + } } /** - * Search for public forked only repos. + * List refs. * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void searchForPublicForkedOnlyRepos() throws IOException { - PagedSearchIterable list = gitHub.searchRepositories() - .user("t0m4uk1991") - .visibility(GHRepository.Visibility.PUBLIC) - .fork(GHFork.FORKS_ONLY) - .list(); - List u = list.toList(); - assertThat(u.size(), is(2)); - assertThat(u.get(0).getName(), is("github-api")); - assertThat(u.get(1).getName(), is("Complete-Python-3-Bootcamp")); - } - - /** - * Search org for repositories. + * @throws Exception + * the exception */ @Test - public void searchOrgForRepositories() { - PagedSearchIterable r = gitHub.searchRepositories().org("hub4j-test-org").list(); - GHRepository u = r.iterator().next(); - assertThat(u.getOwnerName(), equalTo("hub4j-test-org")); - assertThat(r.getTotalCount(), greaterThan(0)); - } + public void listRefs() throws Exception { + GHRepository repo = getRepository(); - /** - * Search repositories. - */ - @Test - public void searchRepositories() { - PagedSearchIterable r = gitHub.searchRepositories() - .q("tetris") - .language("assembly") - .sort(GHRepositorySearchBuilder.Sort.STARS) - .list(); - GHRepository u = r.iterator().next(); - // System.out.println(u.getName()); - assertThat(u.getId(), notNullValue()); - assertThat(u.getLanguage(), equalTo("Assembly")); - assertThat(r.getTotalCount(), greaterThan(0)); - } + List ghRefs; - /** - * Sets the delete branch on merge. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void setDeleteBranchOnMerge() throws IOException { - GHRepository r = getRepository(); + // handle refs/* + ghRefs = repo.listRefs("heads").toList(); + List ghRefsWithPrefix = repo.listRefs("refs/heads").toList(); - // enable auto delete - r.deleteBranchOnMerge(true); + assertThat(ghRefs, notNullValue()); + assertThat(ghRefs.size(), greaterThan(3)); + assertThat(ghRefs.get(0).getRef(), equalTo("refs/heads/changes")); + assertThat(ghRefsWithPrefix.size(), equalTo(ghRefs.size())); + assertThat(ghRefsWithPrefix.get(0).getRef(), equalTo(ghRefs.get(0).getRef())); - r = gitHub.getRepository(r.getFullName()); - assertThat(r.isDeleteBranchOnMerge(), is(true)); + // git/refs/heads/gh-pages + // passing a specific ref to listRefs will fail to parse due to returning a + // single item not an array + try { + ghRefs = repo.listRefs("heads/gh-pages").toList(); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(HttpException.class)); + assertThat(e.getCause(), instanceOf(JsonMappingException.class)); + } - // flip the last value - r.deleteBranchOnMerge(false); + // git/refs/heads/gh + ghRefs = repo.listRefs("heads/gh").toList(); + assertThat(ghRefs, notNullValue()); + assertThat(ghRefs.size(), equalTo(1)); + assertThat(ghRefs.get(0).getRef(), equalTo("refs/heads/gh-pages")); - r = gitHub.getRepository(r.getFullName()); - assertThat(r.isDeleteBranchOnMerge(), is(false)); + // git/refs/headz + try { + ghRefs = repo.listRefs("headz").toList(); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(GHFileNotFoundException.class)); + assertThat(e.getMessage(), + containsString( + "{\"message\":\"Not Found\",\"documentation_url\":\"https://developer.github.com/v3/git/refs/#get-a-reference\"}")); + } } /** - * Sets the merge options. + * Gets the ref. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void setMergeOptions() throws IOException { - // String repoName = "hub4j-test-org/test-mergeoptions"; - GHRepository r = getTempRepository(); + public void getRef() throws Exception { + GHRepository repo = getRepository(); - // at least one merge option must be selected - // flip all the values at least once - r.allowSquashMerge(true); + GHRef ghRef; - r.allowMergeCommit(false); - r.allowRebaseMerge(false); + // handle refs/* + ghRef = repo.getRef("heads/gh-pages"); + GHRef ghRefWithPrefix = repo.getRef("refs/heads/gh-pages"); - r = gitHub.getRepository(r.getFullName()); - assertThat(r.isAllowMergeCommit(), is(false)); - assertThat(r.isAllowRebaseMerge(), is(false)); - assertThat(r.isAllowSquashMerge(), is(true)); + assertThat(ghRef, notNullValue()); + assertThat(ghRef.getRef(), equalTo("refs/heads/gh-pages")); + assertThat(ghRefWithPrefix.getRef(), equalTo(ghRef.getRef())); + assertThat(ghRefWithPrefix.getObject().getType(), equalTo("commit")); + assertThat(ghRefWithPrefix.getObject().getUrl().toString(), + containsString("/repos/hub4j-test-org/github-api/git/commits/")); - // flip the last value - r.allowMergeCommit(true); - r.allowRebaseMerge(true); - r.allowSquashMerge(false); + // git/refs/heads/gh-pages + ghRef = repo.getRef("heads/gh-pages"); + assertThat(ghRef, notNullValue()); + assertThat(ghRef.getRef(), equalTo("refs/heads/gh-pages")); - r = gitHub.getRepository(r.getFullName()); - assertThat(r.isAllowMergeCommit(), is(true)); - assertThat(r.isAllowRebaseMerge(), is(true)); - assertThat(r.isAllowSquashMerge(), is(false)); + // git/refs/heads/gh + try { + ghRef = repo.getRef("heads/gh"); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(GHFileNotFoundException.class)); + assertThat(e.getMessage(), + containsString( + "{\"message\":\"Not Found\",\"documentation_url\":\"https://developer.github.com/v3/git/refs/#get-a-reference\"}")); + } + + // git/refs/headz + try { + ghRef = repo.getRef("headz"); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(GHFileNotFoundException.class)); + assertThat(e.getMessage(), + containsString( + "{\"message\":\"Not Found\",\"documentation_url\":\"https://developer.github.com/v3/git/refs/#get-a-reference\"}")); + } } /** - * Test to check star method by verifying stargarzer count. + * List refs heads. * * @throws Exception * the exception */ @Test - public void starTest() throws Exception { - String owner = "hub4j-test-org"; - GHRepository repository = getRepository(); - assertThat(repository.getOwner().getLogin(), equalTo(owner)); - assertThat(repository.getStargazersCount(), is(1)); - repository.star(); - assertThat(repository.listStargazers().toList().size(), is(2)); - repository.unstar(); - assertThat(repository.listStargazers().toList().size(), is(1)); + public void listRefsHeads() throws Exception { + GHRepository repo = getTempRepository(); + List refs = repo.listRefs("heads").toList(); + assertThat(refs, notNullValue()); + assertThat(refs.size(), equalTo(1)); + assertThat(refs.get(0).getRef(), equalTo("refs/heads/main")); } /** - * Subscription. + * List refs empty tags. * * @throws Exception * the exception */ @Test - public void subscription() throws Exception { - GHRepository r = getRepository(); - assertThat(r.getSubscription(), nullValue()); - GHSubscription s = r.subscribe(true, false); + public void listRefsEmptyTags() throws Exception { try { - - assertThat(r, equalTo(s.getRepository())); - assertThat(s.isIgnored(), equalTo(false)); - assertThat(s.isSubscribed(), equalTo(true)); - assertThat(s.getRepositoryUrl().toString(), containsString("/repos/hub4j-test-org/github-api")); - assertThat(s.getUrl().toString(), containsString("/repos/hub4j-test-org/github-api/subscription")); - - assertThat(s.getReason(), nullValue()); - assertThat(s.getCreatedAt(), equalTo(Instant.ofEpochMilli(1611377286000L))); - } finally { - s.delete(); + GHRepository repo = getTempRepository(); + repo.listRefs("tags").toList(); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(GHFileNotFoundException.class)); + assertThat(e.getMessage(), containsString("/repos/hub4j-test-org/temp-listRefsEmptyTags/git/refs/tags")); } - - assertThat(r.getSubscription(), nullValue()); } /** - * Test sync of fork + * List tags empty. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void sync() throws IOException { - GHRepository r = getRepository(); - assertThat(r.getForksCount(), equalTo(0)); - GHBranchSync sync = r.sync("main"); - assertThat(sync.getOwner().getFullName(), equalTo("hub4j-test-org/github-api")); - assertThat(sync.getMessage(), equalTo("Successfully fetched and fast-forwarded from upstream github-api:main")); - assertThat(sync.getMergeType(), equalTo("fast-forward")); - assertThat(sync.getBaseBranch(), equalTo("github-api:main")); - } - - /** - * Test sync of repository not a fork - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test(expected = HttpException.class) - public void syncNoFork() throws IOException { - GHRepository r = getRepository(); - GHBranchSync sync = r.sync("main"); - fail("Should have thrown an exception"); - + public void listTagsEmpty() throws Exception { + GHRepository repo = getTempRepository(); + List refs = repo.listTags().toList(); + assertThat(refs, notNullValue()); + assertThat(refs, is(empty())); } /** - * Test create repo action variable. + * List tags. * - * @throws IOException + * @throws Exception * the exception */ @Test - public void testCreateRepoActionVariable() throws IOException { - GHRepository repository = getRepository(); - repository.createVariable("MYNEWVARIABLE", "mynewvalue"); - GHRepositoryVariable variable = repository.getVariable("mynewvariable"); - assertThat(variable.getName(), is("MYNEWVARIABLE")); - assertThat(variable.getValue(), is("mynewvalue")); + public void listTags() throws Exception { + GHRepository repo = getRepository(); + List refs = repo.listTags().withPageSize(33).toList(); + assertThat(refs, notNullValue()); + assertThat(refs.size(), greaterThan(90)); } /** - * Tests the creation of repositories with alternating visibilities for orgs. + * Check watchers count. * * @throws Exception * the exception */ @Test - public void testCreateVisibilityForOrganization() throws Exception { - GHOrganization organization = gitHub.getOrganization(GITHUB_API_TEST_ORG); - - // can not test for internal, as test org is not assigned to an enterprise - for (Visibility visibility : Sets.newHashSet(Visibility.PUBLIC, Visibility.PRIVATE)) { - String repoName = String.format("test-repo-visibility-%s", visibility.toString()); - GHRepository repository = organization.createRepository(repoName).visibility(visibility).create(); - try { - assertThat(repository.getVisibility(), is(visibility)); - assertThat(organization.getRepository(repoName).getVisibility(), is(visibility)); - } finally { - repository.delete(); - } - } + public void checkWatchersCount() throws Exception { + snapshotNotAllowed(); + GHRepository repo = getTempRepository(); + int watchersCount = repo.getWatchersCount(); + assertThat(watchersCount, equalTo(10)); } /** - * Tests the creation of repositories with alternating visibilities for users. + * Check stargazers count. * * @throws Exception * the exception */ @Test - public void testCreateVisibilityForUser() throws Exception { - - GHUser myself = gitHub.getMyself(); - - // can not test for internal, as test org is not assigned to an enterprise - for (Visibility visibility : Sets.newHashSet(Visibility.PUBLIC, Visibility.PRIVATE)) { - String repoName = String.format("test-repo-visibility-%s", visibility.toString()); - boolean isPrivate = visibility.equals(Visibility.PRIVATE); - GHRepository repository = gitHub.createRepository(repoName) - .private_(isPrivate) - .visibility(visibility) - .create(); - try { - assertThat(repository.getVisibility(), is(visibility)); - assertThat(myself.getRepository(repoName).getVisibility(), is(visibility)); - } finally { - repository.delete(); - } - } + public void checkStargazersCount() throws Exception { + snapshotNotAllowed(); + GHRepository repo = getTempRepository(); + int stargazersCount = repo.getStargazersCount(); + assertThat(stargazersCount, equalTo(10)); } /** - * Test delete repo action variable. + * List collaborators. * - * @throws IOException + * @throws Exception * the exception */ @Test - public void testDeleteRepoActionVariable() throws IOException { - GHRepository repository = getRepository(); - GHRepositoryVariable variable = repository.getVariable("mynewvariable"); - variable.delete(); - Assert.assertThrows(GHFileNotFoundException.class, () -> repository.getVariable("mynewvariable")); - } - - /** - * Test get repository with visibility. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testGetRepositoryWithVisibility() throws IOException { - snapshotNotAllowed(); - final String repoName = "test-repo-visibility"; - final GHRepository repo = getTempRepository(repoName); - assertThat(repo.getVisibility(), equalTo(Visibility.PUBLIC)); - - repo.setVisibility(Visibility.INTERNAL); - assertThat(gitHub.getRepository(repo.getOwnerName() + "/" + repo.getName()).getVisibility(), - equalTo(Visibility.INTERNAL)); - - repo.setVisibility(Visibility.PRIVATE); - assertThat(gitHub.getRepository(repo.getOwnerName() + "/" + repo.getName()).getVisibility(), - equalTo(Visibility.PRIVATE)); - - repo.setVisibility(Visibility.PUBLIC); - assertThat(gitHub.getRepository(repo.getOwnerName() + "/" + repo.getName()).getVisibility(), - equalTo(Visibility.PUBLIC)); - - // deliberately bogus response in snapshot - assertThat(gitHub.getRepository(repo.getOwnerName() + "/" + repo.getName()).getVisibility(), - equalTo(Visibility.UNKNOWN)); + public void listCollaborators() throws Exception { + GHRepository repo = getRepository(); + List collaborators = repo.listCollaborators().toList(); + assertThat(collaborators.size(), greaterThan(10)); } /** - * Test getRulesForBranch. + * List collaborators filtered. * * @throws Exception * the exception */ @Test - public void testGetRulesForBranch() throws Exception { - GHRepository repository = gitHub.getRepository("ihrigb/node-doorbird"); - List rules = repository.listRulesForBranch("main").toList(); - assertThat(rules.size(), equalTo(3)); - - GHRepositoryRule rule = rules.get(0); - assertThat(rule.getType(), is(equalTo(GHRepositoryRule.Type.DELETION))); - assertThat(rule.getRulesetSourceType(), is(equalTo(GHRepositoryRule.RulesetSourceType.REPOSITORY))); - assertThat(rule.getRulesetSource(), is(equalTo("ihrigb/node-doorbird"))); - assertThat(rule.getRulesetId(), is(equalTo(1170520L))); - - rule = rules.get(1); - assertThat(rule.getType(), is(equalTo(GHRepositoryRule.Type.NON_FAST_FORWARD))); - assertThat(rule.getRulesetSourceType(), is(equalTo(GHRepositoryRule.RulesetSourceType.REPOSITORY))); - assertThat(rule.getRulesetSource(), is(equalTo("ihrigb/node-doorbird"))); - assertThat(rule.getRulesetId(), is(equalTo(1170520L))); - - rule = rules.get(2); - assertThat(rule.getType(), is(equalTo(GHRepositoryRule.Type.PULL_REQUEST))); - assertThat(rule.getRulesetSourceType(), is(equalTo(GHRepositoryRule.RulesetSourceType.REPOSITORY))); - assertThat(rule.getRulesetSource(), is(equalTo("ihrigb/node-doorbird"))); - assertThat(rule.getRulesetId(), is(equalTo(1170520L))); - - // check parameters - assertThat(rule.getParameter(GHRepositoryRule.Parameters.NEGATE).isPresent(), is(equalTo(false))); - assertThat(rule.getParameter(GHRepositoryRule.Parameters.REQUIRED_APPROVING_REVIEW_COUNT).get(), - is(equalTo(1))); - assertThat(rule.getParameter(GHRepositoryRule.Parameters.DISMISS_STALE_REVIEWS_ON_PUSH).get(), - is(equalTo(true))); - assertThat(rule.getParameter(GHRepositoryRule.Parameters.REQUIRE_CODE_OWNER_REVIEW).get(), is(equalTo(false))); + public void listCollaboratorsFiltered() throws Exception { + GHRepository repo = getRepository(); + List allCollaborators = repo.listCollaborators().toList(); + List filteredCollaborators = repo.listCollaborators(GHRepository.CollaboratorAffiliation.OUTSIDE) + .toList(); + assertThat(filteredCollaborators.size(), lessThan(allCollaborators.size())); } /** - * Test getTopReferralPaths. + * User is collaborator. * * @throws Exception * the exception */ @Test - public void testGetTopReferralPaths() throws Exception { - GHRepository repository = gitHub.getRepository("ihrigb/node-doorbird"); - List referralPaths = repository.getTopReferralPaths(); - assertThat(referralPaths.size(), greaterThan(0)); + public void userIsCollaborator() throws Exception { + GHRepository repo = getRepository(); + GHUser collaborator = repo.listCollaborators().toList().get(0); + assertThat(repo.isCollaborator(collaborator), is(true)); } /** - * Test getTopReferralSources. + * Gets the check runs. * * @throws Exception * the exception */ @Test - public void testGetTopReferralSources() throws Exception { - GHRepository repository = gitHub.getRepository("ihrigb/node-doorbird"); - List referralSources = repository.getTopReferralSources(); - assertThat(referralSources.size(), greaterThan(0)); + public void getCheckRuns() throws Exception { + final int expectedCount = 8; + // Use github-api repository as it has checks set up + PagedIterable checkRuns = gitHub.getOrganization("hub4j") + .getRepository("github-api") + .getCheckRuns("78b9ff49d47daaa158eb373c4e2e040f739df8b9"); + // Check if the paging works correctly + assertThat(checkRuns.withPageSize(2).iterator().nextPage(), hasSize(2)); + + // Check if the checkruns are all succeeded and if we got all of them + int checkRunsCount = 0; + for (GHCheckRun checkRun : checkRuns) { + assertThat(checkRun.getConclusion(), equalTo(Conclusion.SUCCESS)); + checkRunsCount++; + } + assertThat(checkRunsCount, equalTo(expectedCount)); + + // Check that we can call update on the results + for (GHCheckRun checkRun : checkRuns) { + checkRun.update(); + } } /** - * Test getters. + * Filter out the checks from a reference * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void testGetters() throws IOException { - GHRepository r = getTempRepository(); - - assertThat(r.hasAdminAccess(), is(true)); - assertThat(r.hasDownloads(), is(true)); - assertThat(r.hasIssues(), is(true)); - assertThat(r.hasPages(), is(false)); - assertThat(r.hasProjects(), is(true)); - assertThat(r.hasPullAccess(), is(true)); - assertThat(r.hasPushAccess(), is(true)); - assertThat(r.hasWiki(), is(true)); - - assertThat(r.isAllowMergeCommit(), is(true)); - assertThat(r.isAllowRebaseMerge(), is(true)); - assertThat(r.isAllowSquashMerge(), is(true)); - assertThat(r.isAllowForking(), is(false)); - - String httpTransport = "https://github.com/hub4j-test-org/temp-testGetters.git"; - assertThat(r.getHttpTransportUrl(), equalTo(httpTransport)); - assertThat(r.getGitTransportUrl(), equalTo("git://github.com/hub4j-test-org/temp-testGetters.git")); - assertThat(r.getSvnUrl(), equalTo("https://github.com/hub4j-test-org/temp-testGetters")); - assertThat(r.getMirrorUrl(), nullValue()); - assertThat(r.getSshUrl(), equalTo("git@github.com:hub4j-test-org/temp-testGetters.git")); - assertThat(r.getHtmlUrl().toString(), equalTo("https://github.com/hub4j-test-org/temp-testGetters")); - assertThat(r.getOpenIssueCount(), equalTo(0)); - assertThat(r.getSubscribersCount(), equalTo(7)); + public void getCheckRunsWithParams() throws Exception { + final int expectedCount = 1; + // Use github-api repository as it has checks set up + final Map params = new HashMap<>(1); + params.put("check_name", "build-only (Java 17)"); + PagedIterable checkRuns = gitHub.getOrganization("hub4j") + .getRepository("github-api") + .getCheckRuns("54d60fbb53b4efa19f3081417bfb6a1de30c55e4", params); - assertThat(r.getName(), equalTo("temp-testGetters")); - assertThat(r.getFullName(), equalTo("hub4j-test-org/temp-testGetters")); + // Check if the checkruns are all succeeded and if we got all of them + int checkRunsCount = 0; + for (GHCheckRun checkRun : checkRuns) { + assertThat(checkRun.getConclusion(), equalTo(Conclusion.SUCCESS)); + checkRunsCount++; + } + assertThat(checkRunsCount, equalTo(expectedCount)); } /** - * Test getVulnerabilityAlerts. + * Gets the last commit status. * * @throws Exception * the exception */ @Test - public void testIsVulnerabilityAlertsEnabled() throws Exception { - GHRepository repository = gitHub.getRepository("ihrigb/node-doorbird"); - assertThat(repository.isVulnerabilityAlertsEnabled(), is(true)); + public void getLastCommitStatus() throws Exception { + GHCommitStatus status = getRepository().getLastCommitStatus("8051615eff597f4e49f4f47625e6fc2b49f26bfc"); + assertThat(status.getId(), equalTo(9027542286L)); + assertThat(status.getState(), equalTo(GHCommitState.SUCCESS)); + assertThat(status.getContext(), equalTo("ci/circleci: build")); } /** - * Test issue 162. + * List commits between. * * @throws Exception * the exception */ - @Test // issue #162 - public void testIssue162() throws Exception { - GHRepository r = gitHub.getRepository("hub4j/github-api"); - List contents = r.getDirectoryContent("", "gh-pages"); - for (GHContent content : contents) { - if (content.isFile()) { - String content1 = content.getContent(); - String content2 = r.getFileContent(content.getPath(), "gh-pages").getContent(); - // System.out.println(content.getPath()); - assertThat(content2, equalTo(content1)); - } + @Test + public void listCommitsBetween() throws Exception { + GHRepository repository = getRepository(); + int startingCount = mockGitHub.getRequestCount(); + GHCompare compare = repository.getCompare("e46a9f3f2ac55db96de3c5c4706f2813b3a96465", + "8051615eff597f4e49f4f47625e6fc2b49f26bfc"); + int actualCount = 0; + for (GHCompare.Commit item : compare.listCommits().withPageSize(5)) { + assertThat(item, notNullValue()); + actualCount++; } + assertThat(compare.getTotalCommits(), is(9)); + assertThat(actualCount, is(9)); + assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 1)); } /** - * Test searching for pull requests. + * List commits between paginated. + * + * @throws Exception + * the exception + */ + @Test + public void listCommitsBetweenPaginated() throws Exception { + GHRepository repository = getRepository(); + int startingCount = mockGitHub.getRequestCount(); + repository.setCompareUsePaginatedCommits(true); + GHCompare compare = repository.getCompare("e46a9f3f2ac55db96de3c5c4706f2813b3a96465", + "8051615eff597f4e49f4f47625e6fc2b49f26bfc"); + int actualCount = 0; + for (GHCompare.Commit item : compare.listCommits().withPageSize(5)) { + assertThat(item, notNullValue()); + actualCount++; + } + assertThat(compare.getTotalCommits(), is(9)); + assertThat(actualCount, is(9)); + assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 3)); + } + + /** + * Gets the commits between over 250. + * + * @throws Exception + * the exception + */ + @Test + public void getCommitsBetweenOver250() throws Exception { + GHRepository repository = getRepository(); + int startingCount = mockGitHub.getRequestCount(); + GHCompare compare = repository.getCompare("4261c42949915816a9f246eb14c3dfd21a637bc2", + "94ff089e60064bfa43e374baeb10846f7ce82f40"); + int actualCount = 0; + for (GHCompare.Commit item : compare.getCommits()) { + assertThat(item, notNullValue()); + actualCount++; + } + assertThat(compare.getTotalCommits(), is(283)); + assertThat(actualCount, is(250)); + assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 1)); + + // Additional GHCompare checks + assertThat(compare.getAheadBy(), equalTo(283)); + assertThat(compare.getBehindBy(), equalTo(0)); + assertThat(compare.getStatus(), equalTo(GHCompare.Status.ahead)); + assertThat(compare.getDiffUrl().toString(), + endsWith( + "compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40.diff")); + assertThat(compare.getHtmlUrl().toString(), + endsWith( + "compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40")); + assertThat(compare.getPatchUrl().toString(), + endsWith( + "compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40.patch")); + assertThat(compare.getPermalinkUrl().toString(), + endsWith("compare/hub4j-test-org:4261c42...hub4j-test-org:94ff089")); + assertThat(compare.getUrl().toString(), + endsWith( + "compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40")); + + assertThat(compare.getBaseCommit().getSHA1(), equalTo("4261c42949915816a9f246eb14c3dfd21a637bc2")); + + assertThat(compare.getMergeBaseCommit().getSHA1(), equalTo("4261c42949915816a9f246eb14c3dfd21a637bc2")); + // it appears this field is not present in the returned JSON. Strange. + assertThat(compare.getMergeBaseCommit().getCommit().getSha(), nullValue()); + assertThat(compare.getMergeBaseCommit().getCommit().getUrl(), + endsWith("/commits/4261c42949915816a9f246eb14c3dfd21a637bc2")); + assertThat(compare.getMergeBaseCommit().getCommit().getMessage(), + endsWith("[maven-release-plugin] prepare release github-api-1.123")); + assertThat(compare.getMergeBaseCommit().getCommit().getAuthor().getName(), equalTo("Liam Newman")); + assertThat(compare.getMergeBaseCommit().getCommit().getCommitter().getName(), equalTo("Liam Newman")); + + assertThat(compare.getMergeBaseCommit().getCommit().getTree().getSha(), + equalTo("5da98090976978c93aba0bdfa550e05675543f99")); + assertThat(compare.getMergeBaseCommit().getCommit().getTree().getUrl(), + endsWith("/git/trees/5da98090976978c93aba0bdfa550e05675543f99")); + + assertThat(compare.getFiles().length, equalTo(300)); + assertThat(compare.getFiles()[0].getFileName(), equalTo(".github/PULL_REQUEST_TEMPLATE.md")); + assertThat(compare.getFiles()[0].getLinesAdded(), equalTo(8)); + assertThat(compare.getFiles()[0].getLinesChanged(), equalTo(15)); + assertThat(compare.getFiles()[0].getLinesDeleted(), equalTo(7)); + assertThat(compare.getFiles()[0].getFileName(), equalTo(".github/PULL_REQUEST_TEMPLATE.md")); + assertThat(compare.getFiles()[0].getPatch(), startsWith("@@ -1,15 +1,16 @@")); + assertThat(compare.getFiles()[0].getPreviousFilename(), nullValue()); + assertThat(compare.getFiles()[0].getStatus(), equalTo("modified")); + assertThat(compare.getFiles()[0].getSha(), equalTo("e4234f5f6f39899282a6ef1edff343ae1269222e")); + + assertThat(compare.getFiles()[0].getBlobUrl().toString(), + endsWith("/blob/94ff089e60064bfa43e374baeb10846f7ce82f40/.github/PULL_REQUEST_TEMPLATE.md")); + assertThat(compare.getFiles()[0].getRawUrl().toString(), + endsWith("/raw/94ff089e60064bfa43e374baeb10846f7ce82f40/.github/PULL_REQUEST_TEMPLATE.md")); + } + + /** + * Gets the commits between paged. + * + * @throws Exception + * the exception + */ + @Test + public void getCommitsBetweenPaged() throws Exception { + GHRepository repository = getRepository(); + int startingCount = mockGitHub.getRequestCount(); + repository.setCompareUsePaginatedCommits(true); + GHCompare compare = repository.getCompare("4261c42949915816a9f246eb14c3dfd21a637bc2", + "94ff089e60064bfa43e374baeb10846f7ce82f40"); + int actualCount = 0; + for (GHCompare.Commit item : compare.getCommits()) { + assertThat(item, notNullValue()); + actualCount++; + } + assertThat(compare.getTotalCommits(), is(283)); + assertThat(actualCount, is(283)); + assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 4)); + } + + /** + * Creates the dispatch event without client payload. * * @throws Exception * the exception */ @Test + public void createDispatchEventWithoutClientPayload() throws Exception { + GHRepository repository = getTempRepository(); + repository.dispatch("test", null); + } + + /** + * Creates the dispatch event with client payload. + * + * @throws Exception + * the exception + */ + @Test + public void createDispatchEventWithClientPayload() throws Exception { + GHRepository repository = getTempRepository(); + Map clientPayload = new HashMap<>(); + clientPayload.put("name", "joe.doe"); + clientPayload.put("list", new ArrayList<>()); + repository.dispatch("test", clientPayload); + } + + /** + * Creates the secret. + * + * @throws Exception + * the exception + */ + @Test + public void createSecret() throws Exception { + GHRepository repo = getTempRepository(); + repo.createSecret("secret", "encrypted", "public"); + } + + /** + * Test to check star method by verifying stargarzer count. + * + * @throws Exception + * the exception + */ + @Test + public void starTest() throws Exception { + String owner = "hub4j-test-org"; + GHRepository repository = getRepository(); + assertThat(repository.getOwner().getLogin(), equalTo(owner)); + assertThat(repository.getStargazersCount(), is(1)); + repository.star(); + assertThat(repository.listStargazers().toList().size(), is(2)); + repository.unstar(); + assertThat(repository.listStargazers().toList().size(), is(1)); + } + + /** + * Test create repo action variable. + * + * @throws IOException + * the exception + */ + @Test + public void testCreateRepoActionVariable() throws IOException { + GHRepository repository = getRepository(); + repository.createVariable("MYNEWVARIABLE", "mynewvalue"); + GHRepositoryVariable variable = repository.getVariable("mynewvariable"); + assertThat(variable.getName(), is("MYNEWVARIABLE")); + assertThat(variable.getValue(), is("mynewvalue")); + } + + /** + * Test update repo action variable. + * + * @throws IOException + * the exception + */ + @Test + public void testUpdateRepoActionVariable() throws IOException { + GHRepository repository = getRepository(); + GHRepositoryVariable variable = repository.getVariable("MYNEWVARIABLE"); + variable.set().value("myupdatevalue"); + variable = repository.getVariable("MYNEWVARIABLE"); + assertThat(variable.getValue(), is("myupdatevalue")); + } + + /** + * Test delete repo action variable. + * + * @throws IOException + * the exception + */ + @Test + public void testDeleteRepoActionVariable() throws IOException { + GHRepository repository = getRepository(); + GHRepositoryVariable variable = repository.getVariable("mynewvariable"); + variable.delete(); + Assert.assertThrows(GHFileNotFoundException.class, () -> repository.getVariable("mynewvariable")); + } + + /** + * Test demoing the issue with a user having the maintain permission on a repository. + * + * Test checking the permission fallback mechanism in case the Github API changes. The test was recorded at a time a + * new permission was added by mistake. If a re-recording it is needed, you'll like have to manually edit the + * generated mocks to get a non existing permission See + * https://github.com/hub4j/github-api/issues/1671#issuecomment-1577515662 for the details. + * + * @throws IOException + * the exception + */ + @Test + public void cannotRetrievePermissionMaintainUser() throws IOException { + GHRepository r = gitHub.getRepository("hub4j-test-org/maintain-permission-issue"); + GHPermissionType permission = r.getPermission("alecharp"); + assertThat(permission.toString(), is("UNKNOWN")); + } + + /** + * Test searching for pull requests. + * + * @throws IOException + * the exception + */ + @Test public void testSearchPullRequests() throws Exception { GHRepository repository = gitHub.getRepository("kgromov/temp-testSearchPullRequests"); // prepare branches @@ -1694,300 +1834,132 @@ public void testSearchPullRequests() throws Exception { searchResult = search.list(); this.verifySingleResult(searchResult, mergedPR); - search = repository.searchPullRequests() - .createdBefore(afterRange, false) - .updatedBefore(afterRange, false) - .closedBefore(afterRange, true) - .mergedBefore(afterRange, false); - searchResult = search.list(); - this.verifySingleResult(searchResult, mergedPR); - - // search by version control - Map branches = repository.getBranches(); - search = repository.searchPullRequests() - .base(branches.get("main")) - .head(branches.get("branchToMerge")) - .commit(commit.getCommit().getSha()); - searchResult = search.list(); - this.verifySingleResult(searchResult, mergedPR); - - // search by remaining filters - search = repository.searchPullRequests() - .titleLike("Temp") - .sort(GHPullRequestSearchBuilder.Sort.CREATED) - .order(GHDirection.ASC); - searchResult = search.list(); - this.verifyPluralResult(searchResult, draftPR, mergedPR); - - search = repository.searchPullRequests().inLabels(Arrays.asList("test")).order(GHDirection.DESC); - searchResult = search.list(); - this.verifyPluralResult(searchResult, mergedPR, draftPR); - - search = repository.searchPullRequests().assigned(myself).mentions(myself); - searchResult = search.list(); - this.verifySingleResult(searchResult, mergedPR); - } - - /** - * Test set public. - * - * @throws Exception - * the exception - */ - @Test - public void testSetPublic() throws Exception { - kohsuke(); - GHUser myself = gitHub.getMyself(); - String repoName = "test-repo-public"; - GHRepository repo = gitHub.createRepository(repoName).private_(false).create(); - try { - assertThat(repo.isPrivate(), is(false)); - repo.setPrivate(true); - assertThat(myself.getRepository(repoName).isPrivate(), is(true)); - repo.setPrivate(false); - assertThat(myself.getRepository(repoName).isPrivate(), is(false)); - } finally { - repo.delete(); - } - } - - /** - * Test set topics. - * - * @throws Exception - * the exception - */ - @Test - public void testSetTopics() throws Exception { - GHRepository repo = getRepository(gitHub); - - List topics = new ArrayList<>(); + search = repository.searchPullRequests() + .createdBefore(afterRange, false) + .updatedBefore(afterRange, false) + .closedBefore(afterRange, true) + .mergedBefore(afterRange, false); + searchResult = search.list(); + this.verifySingleResult(searchResult, mergedPR); - topics.add("java"); - topics.add("api-test-dummy"); - repo.setTopics(topics); - assertThat("Topics retain input order (are not sort when stored)", - repo.listTopics(), - contains("java", "api-test-dummy")); + // search by version control + Map branches = repository.getBranches(); + search = repository.searchPullRequests() + .base(branches.get("main")) + .head(branches.get("branchToMerge")) + .commit(commit.getCommit().getSha()); + searchResult = search.list(); + this.verifySingleResult(searchResult, mergedPR); - topics = new ArrayList<>(); - topics.add("ordered-state"); - topics.add("api-test-dummy"); - topics.add("java"); - repo.setTopics(topics); - assertThat("Topics behave as a set and retain order from previous calls", - repo.listTopics(), - contains("java", "api-test-dummy", "ordered-state")); + // search by remaining filters + search = repository.searchPullRequests() + .titleLike("Temp") + .sort(GHPullRequestSearchBuilder.Sort.CREATED) + .order(GHDirection.ASC); + searchResult = search.list(); + this.verifyPluralResult(searchResult, draftPR, mergedPR); - topics = new ArrayList<>(); - topics.add("ordered-state"); - topics.add("api-test-dummy"); - repo.setTopics(topics); - assertThat("Topics retain order even when some are removed", - repo.listTopics(), - contains("api-test-dummy", "ordered-state")); + search = repository.searchPullRequests().inLabels(Arrays.asList("test")).order(GHDirection.DESC); + searchResult = search.list(); + this.verifyPluralResult(searchResult, mergedPR, draftPR); - topics = new ArrayList<>(); - repo.setTopics(topics); - assertThat("Topics can be set to empty", repo.listTopics(), is(empty())); + search = repository.searchPullRequests().assigned(myself).mentions(myself); + searchResult = search.list(); + this.verifySingleResult(searchResult, mergedPR); } /** - * Test tarball. + * Test getTopReferralPaths. * - * @throws IOException - * Signals that an I/O exception has occurred. + * @throws Exception + * the exception */ @Test - public void testTarball() throws IOException { - getTempRepository().readTar((InputStream inputstream) -> { - return new ByteArrayInputStream(IOUtils.toByteArray(inputstream)); - }, null); + public void testGetTopReferralPaths() throws Exception { + GHRepository repository = gitHub.getRepository("ihrigb/node-doorbird"); + List referralPaths = repository.getTopReferralPaths(); + assertThat(referralPaths.size(), greaterThan(0)); } /** - * Test update repo action variable. + * Test getTopReferralSources. * - * @throws IOException + * @throws Exception * the exception */ @Test - public void testUpdateRepoActionVariable() throws IOException { - GHRepository repository = getRepository(); - GHRepositoryVariable variable = repository.getVariable("MYNEWVARIABLE"); - variable.set().value("myupdatevalue"); - variable = repository.getVariable("MYNEWVARIABLE"); - assertThat(variable.getValue(), is("myupdatevalue")); + public void testGetTopReferralSources() throws Exception { + GHRepository repository = gitHub.getRepository("ihrigb/node-doorbird"); + List referralSources = repository.getTopReferralSources(); + assertThat(referralSources.size(), greaterThan(0)); } /** - * Test update repository. + * Test getRulesForBranch. * * @throws Exception * the exception */ @Test - public void testUpdateRepository() throws Exception { - String homepage = "https://github-api.kohsuke.org/apidocs/index.html"; - String description = "A test repository for update testing via the github-api project"; - - GHRepository repo = getTempRepository(); - GHRepository.Updater builder = repo.update(); - - // one merge option is always required - GHRepository updated = builder.allowRebaseMerge(false) - .allowSquashMerge(false) - .deleteBranchOnMerge(true) - .allowForking(true) - .description(description) - .downloads(false) - .downloads(false) - .homepage(homepage) - .issues(false) - .private_(true) - .projects(false) - .wiki(false) - .done(); - - assertThat(updated.isAllowMergeCommit(), is(true)); - assertThat(updated.isAllowRebaseMerge(), is(false)); - assertThat(updated.isAllowSquashMerge(), is(false)); - assertThat(updated.isDeleteBranchOnMerge(), is(true)); - assertThat(updated.isAllowForking(), is(true)); - assertThat(updated.isPrivate(), is(true)); - assertThat(updated.hasDownloads(), is(false)); - assertThat(updated.hasIssues(), is(false)); - assertThat(updated.hasProjects(), is(false)); - assertThat(updated.hasWiki(), is(false)); - - assertThat(updated.getHomepage(), equalTo(homepage)); - assertThat(updated.getDescription(), equalTo(description)); - - // test the other merge option and making the repo public again - GHRepository redux = updated.update().allowMergeCommit(false).allowRebaseMerge(true).private_(false).done(); + public void testGetRulesForBranch() throws Exception { + GHRepository repository = gitHub.getRepository("ihrigb/node-doorbird"); + List rules = repository.listRulesForBranch("main").toList(); + assertThat(rules.size(), equalTo(3)); - assertThat(redux.isAllowMergeCommit(), is(false)); - assertThat(redux.isAllowRebaseMerge(), is(true)); - assertThat(redux.isPrivate(), is(false)); + GHRepositoryRule rule = rules.get(0); + assertThat(rule.getType(), is(equalTo(GHRepositoryRule.Type.DELETION))); + assertThat(rule.getRulesetSourceType(), is(equalTo(GHRepositoryRule.RulesetSourceType.REPOSITORY))); + assertThat(rule.getRulesetSource(), is(equalTo("ihrigb/node-doorbird"))); + assertThat(rule.getRulesetId(), is(equalTo(1170520L))); - String updatedDescription = "updated using set()"; - redux = redux.set().description(updatedDescription); + rule = rules.get(1); + assertThat(rule.getType(), is(equalTo(GHRepositoryRule.Type.NON_FAST_FORWARD))); + assertThat(rule.getRulesetSourceType(), is(equalTo(GHRepositoryRule.RulesetSourceType.REPOSITORY))); + assertThat(rule.getRulesetSource(), is(equalTo("ihrigb/node-doorbird"))); + assertThat(rule.getRulesetId(), is(equalTo(1170520L))); - assertThat(redux.getDescription(), equalTo(updatedDescription)); - } + rule = rules.get(2); + assertThat(rule.getType(), is(equalTo(GHRepositoryRule.Type.PULL_REQUEST))); + assertThat(rule.getRulesetSourceType(), is(equalTo(GHRepositoryRule.RulesetSourceType.REPOSITORY))); + assertThat(rule.getRulesetSource(), is(equalTo("ihrigb/node-doorbird"))); + assertThat(rule.getRulesetId(), is(equalTo(1170520L))); - /** - * Test zipball. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testZipball() throws IOException { - getTempRepository().readZip((InputStream inputstream) -> { - return new ByteArrayInputStream(IOUtils.toByteArray(inputstream)); - }, null); + // check parameters + assertThat(rule.getParameter(GHRepositoryRule.Parameters.NEGATE).isPresent(), is(equalTo(false))); + assertThat(rule.getParameter(GHRepositoryRule.Parameters.REQUIRED_APPROVING_REVIEW_COUNT).get(), + is(equalTo(1))); + assertThat(rule.getParameter(GHRepositoryRule.Parameters.DISMISS_STALE_REVIEWS_ON_PUSH).get(), + is(equalTo(true))); + assertThat(rule.getParameter(GHRepositoryRule.Parameters.REQUIRE_CODE_OWNER_REVIEW).get(), is(equalTo(false))); } /** - * User is collaborator. + * Test getVulnerabilityAlerts. * * @throws Exception * the exception */ @Test - public void userIsCollaborator() throws Exception { - GHRepository repo = getRepository(); - GHUser collaborator = repo.listCollaborators().toList().get(0); - assertThat(repo.isCollaborator(collaborator), is(true)); - } - - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); - } - - @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", - justification = "It causes a performance degradation, but we have already exposed it to the API") - private Set setupPostCommitHooks(final GHRepository repo) { - return new AbstractSet() { - @Override - public boolean add(URL url) { - try { - repo.createWebHook(url); - return true; - } catch (IOException e) { - throw new GHException("Failed to update post-commit hooks", e); - } - } - - @Override - public Iterator iterator() { - return getPostCommitHooks().iterator(); - } - - @Override - public boolean remove(Object url) { - try { - String _url = ((URL) url).toExternalForm(); - for (GHHook h : repo.getHooks()) { - if (h.getName().equals("web") && h.getConfig().get("url").equals(_url)) { - h.delete(); - return true; - } - } - return false; - } catch (IOException e) { - throw new GHException("Failed to update post-commit hooks", e); - } - } - - @Override - public int size() { - return getPostCommitHooks().size(); - } - - private List getPostCommitHooks() { - try { - List r = new ArrayList<>(); - for (GHHook h : repo.getHooks()) { - if (h.getName().equals("web")) { - r.add(new URL(h.getConfig().get("url"))); - } - } - return r; - } catch (IOException e) { - throw new GHException("Failed to retrieve post-commit hooks", e); - } - } - }; + public void testIsVulnerabilityAlertsEnabled() throws Exception { + GHRepository repository = gitHub.getRepository("ihrigb/node-doorbird"); + assertThat(repository.isVulnerabilityAlertsEnabled(), is(true)); } private void verifyEmptyResult(PagedSearchIterable searchResult) { assertThat(searchResult.getTotalCount(), is(0)); } - private void verifyPluralResult(PagedSearchIterable searchResult, - GHPullRequest expectedPR1, - GHPullRequest expectedPR2) throws IOException { - assertThat(searchResult.getTotalCount(), is(2)); - assertThat(searchResult.toList().get(0).getNumber(), is(expectedPR1.getNumber())); - assertThat(searchResult.toList().get(1).getNumber(), is(expectedPR2.getNumber())); - } - private void verifySingleResult(PagedSearchIterable searchResult, GHPullRequest expectedPR) throws IOException { assertThat(searchResult.getTotalCount(), is(1)); assertThat(searchResult.toList().get(0).getNumber(), is(expectedPR.getNumber())); } - /** - * Gets the repository. - * - * @return the repository - * @throws IOException - * Signals that an I/O exception has occurred. - */ - protected GHRepository getRepository() throws IOException { - return getRepository(gitHub); + private void verifyPluralResult(PagedSearchIterable searchResult, + GHPullRequest expectedPR1, + GHPullRequest expectedPR2) throws IOException { + assertThat(searchResult.getTotalCount(), is(2)); + assertThat(searchResult.toList().get(0).getNumber(), is(expectedPR1.getNumber())); + assertThat(searchResult.toList().get(1).getNumber(), is(expectedPR2.getNumber())); } } diff --git a/src/test/java/org/kohsuke/github/GHTagTest.java b/src/test/java/org/kohsuke/github/GHTagTest.java index cec99eddeb..48f990f3dc 100644 --- a/src/test/java/org/kohsuke/github/GHTagTest.java +++ b/src/test/java/org/kohsuke/github/GHTagTest.java @@ -24,10 +24,13 @@ public GHTagTest() { /** * Clean up tags. + * + * @throws Exception + * the exception */ @Before @After - public void cleanUpTags() { + public void cleanUpTags() throws Exception { // Cleanup is only needed when proxying if (!mockGitHub.isUseProxy()) { return; @@ -75,10 +78,6 @@ public void testCreateTag() throws Exception { assertThat(ref, notNullValue()); } - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); - } - /** * Gets the repository. * @@ -89,4 +88,8 @@ private GHRepository getRepository(GitHub gitHub) throws IOException { protected GHRepository getRepository() throws IOException { return getRepository(gitHub); } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } } diff --git a/src/test/java/org/kohsuke/github/GHTeamTest.java b/src/test/java/org/kohsuke/github/GHTeamTest.java index fa80ce605c..1bd3ea6bae 100644 --- a/src/test/java/org/kohsuke/github/GHTeamTest.java +++ b/src/test/java/org/kohsuke/github/GHTeamTest.java @@ -29,72 +29,34 @@ public GHTeamTest() { } /** - * Adds the remove member. + * Test set description. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void addRemoveMember() throws IOException { + public void testSetDescription() throws IOException { + + String description = "Updated by API Test"; String teamSlug = "dummy-team"; + // Set the description. GHTeam team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); + assertThat(team.getHtmlUrl(), notNullValue()); + team.setDescription(description); - List members = team.listMembers().toList(); - - assertThat(members, notNullValue()); - assertThat("One admin in dummy team", members.size(), equalTo(1)); - assertThat("Specific user in admin team", - members.stream().anyMatch(ghUser -> ghUser.getLogin().equals("bitwiseman"))); - - GHUser user = gitHub.getUser("gsmet"); - - try { - team.add(user, Role.MAINTAINER); - - // test all - members = team.listMembers().toList(); - - assertThat(members, notNullValue()); - assertThat("Two members for all roles in dummy team", members.size(), equalTo(2)); - assertThat("Specific users in team", - members, - containsInAnyOrder(hasProperty("login", equalTo("bitwiseman")), - hasProperty("login", equalTo("gsmet")))); - - // test maintainer role filter - members = team.listMembers(Role.MAINTAINER).toList(); - - assertThat(members, notNullValue()); - assertThat("Two members for all roles in dummy team", members.size(), equalTo(2)); - assertThat("Specific users in team", - members, - containsInAnyOrder(hasProperty("login", equalTo("bitwiseman")), - hasProperty("login", equalTo("gsmet")))); - - // test member role filter - // it's hard to test this as owner of the org are automatically made maintainer - // so let's just test that we don't have any members around - members = team.listMembers(Role.MEMBER).toList(); - - assertThat(members, notNullValue()); - assertThat("No members in dummy team", members.size(), equalTo(0)); + // Check that it was set correctly. + team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); + assertThat(team.getDescription(), equalTo(description)); - // test removing the user has effect - team.remove(user); + description += "Modified"; - members = team.listMembers().toList(); + // Set the description. + team.setDescription(description); - assertThat(members, notNullValue()); - assertThat("One member for all roles in dummy team", members.size(), equalTo(1)); - assertThat("Specific user in team", - members, - containsInAnyOrder(hasProperty("login", equalTo("bitwiseman")))); - } finally { - if (team.hasMember(user)) { - team.remove(user); - } - } + // Check that it was set correctly. + team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); + assertThat(team.getDescription(), equalTo(description)); } /** @@ -175,269 +137,307 @@ public void listMembersNoMatch() throws IOException { } /** - * Test fail to connect to external group from other organization. + * Test set privacy. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testConnectToExternalGroupByGroup() throws IOException { - String teamSlug = "acme-developers"; + public void testSetPrivacy() throws IOException { + // we need to use a team that doesn't have child teams + // as secret privacy is not supported for parent teams + String teamSlug = "simple-team"; + Privacy privacy = Privacy.CLOSED; - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHTeam team = org.getTeamBySlug(teamSlug); - GHExternalGroup group = org.getExternalGroup(467431); + // Set the privacy. + GHTeam team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); + team.setPrivacy(privacy); - GHExternalGroup connectedGroup = team.connectToExternalGroup(group); + // Check that it was set correctly. + team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); + assertThat(team.getPrivacy(), equalTo(privacy)); - assertThat(connectedGroup.getId(), equalTo(467431L)); - assertThat(connectedGroup.getName(), equalTo("acme-developers")); - assertThat(connectedGroup.getUpdatedAt(), notNullValue()); + privacy = Privacy.SECRET; - assertThat(connectedGroup.getMembers(), notNullValue()); - assertThat(membersSummary(connectedGroup), - hasItems("158311279:john-doe_acme:John Doe:john.doe@acme.corp", - "166731041:jane-doe_acme:Jane Doe:jane.doe@acme.corp")); + // Set the privacy. + team.setPrivacy(privacy); - assertThat(group.getTeams(), notNullValue()); - assertThat(teamSummary(connectedGroup), hasItems("34519919:ACME-DEVELOPERS")); + // Check that it was set correctly. + team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); + assertThat(team.getPrivacy(), equalTo(privacy)); } /** - * Test connect to external group by id. + * Test fetch child teams. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testConnectToExternalGroupById() throws IOException { - String teamSlug = "acme-developers"; + public void testFetchChildTeams() throws IOException { + String teamSlug = "dummy-team"; GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHTeam team = org.getTeamBySlug(teamSlug); + Set result = team.listChildTeams().toSet(); - final GHExternalGroup group = team.connectToExternalGroup(467431); - - assertThat(group.getId(), equalTo(467431L)); - assertThat(group.getName(), equalTo("acme-developers")); - assertThat(group.getUpdatedAt(), notNullValue()); - - assertThat(group.getMembers(), notNullValue()); - assertThat(membersSummary(group), - hasItems("158311279:john-doe_acme:John Doe:john.doe@acme.corp", - "166731041:jane-doe_acme:Jane Doe:jane.doe@acme.corp")); - - assertThat(group.getTeams(), notNullValue()); - assertThat(teamSummary(group), hasItems("34519919:ACME-DEVELOPERS")); + assertThat(result.size(), equalTo(1)); + assertThat(result.toArray(new GHTeam[]{})[0].getName(), equalTo("child-team-for-dummy")); } /** - * Test delete connection to external group + * Test fetch empty child teams. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testDeleteExternalGroupConnection() throws IOException { - String teamSlug = "acme-developers"; + public void testFetchEmptyChildTeams() throws IOException { + String teamSlug = "simple-team"; GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHTeam team = org.getTeamBySlug(teamSlug); + Set result = team.listChildTeams().toSet(); - team.deleteExternalGroupConnection(); - - mockGitHub.apiServer() - .verify(1, - deleteRequestedFor(urlPathEqualTo("/orgs/" + team.getOrganization().getLogin() + "/teams/" - + team.getSlug() + "/external-groups"))); + assertThat(result, is(empty())); } /** - * Test failure when connecting to external group by id. + * Adds the remove member. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testFailConnectToExternalGroupTeamIsNotAvailableInOrg() throws IOException { - String teamSlug = "acme-developers"; + public void addRemoveMember() throws IOException { + String teamSlug = "dummy-team"; - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHTeam team = org.getTeamBySlug(teamSlug); + GHTeam team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); - assertThrows(GHFileNotFoundException.class, () -> team.connectToExternalGroup(12345)); + List members = team.listMembers().toList(); + + assertThat(members, notNullValue()); + assertThat("One admin in dummy team", members.size(), equalTo(1)); + assertThat("Specific user in admin team", + members.stream().anyMatch(ghUser -> ghUser.getLogin().equals("bitwiseman"))); + + GHUser user = gitHub.getUser("gsmet"); + + try { + team.add(user, Role.MAINTAINER); + + // test all + members = team.listMembers().toList(); + + assertThat(members, notNullValue()); + assertThat("Two members for all roles in dummy team", members.size(), equalTo(2)); + assertThat("Specific users in team", + members, + containsInAnyOrder(hasProperty("login", equalTo("bitwiseman")), + hasProperty("login", equalTo("gsmet")))); + + // test maintainer role filter + members = team.listMembers(Role.MAINTAINER).toList(); + + assertThat(members, notNullValue()); + assertThat("Two members for all roles in dummy team", members.size(), equalTo(2)); + assertThat("Specific users in team", + members, + containsInAnyOrder(hasProperty("login", equalTo("bitwiseman")), + hasProperty("login", equalTo("gsmet")))); + + // test member role filter + // it's hard to test this as owner of the org are automatically made maintainer + // so let's just test that we don't have any members around + members = team.listMembers(Role.MEMBER).toList(); + + assertThat(members, notNullValue()); + assertThat("No members in dummy team", members.size(), equalTo(0)); + + // test removing the user has effect + team.remove(user); + + members = team.listMembers().toList(); + + assertThat(members, notNullValue()); + assertThat("One member for all roles in dummy team", members.size(), equalTo(1)); + assertThat("Specific user in team", + members, + containsInAnyOrder(hasProperty("login", equalTo("bitwiseman")))); + } finally { + if (team.hasMember(user)) { + team.remove(user); + } + } } /** - * Test failure when connecting to external group by id. + * Test get external groups. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testFailConnectToExternalGroupWhenTeamHasMembers() throws IOException { + public void testGetExternalGroups() throws IOException { String teamSlug = "acme-developers"; GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHTeam team = org.getTeamBySlug(teamSlug); + final List groups = team.getExternalGroups(); - final GHIOException failure = assertThrows(GHTeamCannotBeExternallyManagedException.class, - () -> team.connectToExternalGroup(467431)); - assertThat(failure.getMessage(), equalTo("Could not connect team to external group")); + assertThat(groups, notNullValue()); + assertThat(groups.size(), equalTo(1)); + assertThat(groupSummary(groups), hasItems("467431:acme-developers")); + + groups.forEach(group -> assertThat(group, isExternalGroupSummary())); } /** - * Test fetch child teams. + * Test get external groups from not enterprise managed organization. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testFetchChildTeams() throws IOException { - String teamSlug = "dummy-team"; + public void testGetExternalGroupsNotEnterpriseManagedOrganization() throws IOException { + String teamSlug = "acme-developers"; GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHTeam team = org.getTeamBySlug(teamSlug); - Set result = team.listChildTeams().toSet(); - assertThat(result.size(), equalTo(1)); - assertThat(result.toArray(new GHTeam[]{})[0].getName(), equalTo("child-team-for-dummy")); + final GHIOException failure = assertThrows(GHNotExternallyManagedEnterpriseException.class, + () -> team.getExternalGroups()); + assertThat(failure.getMessage(), equalTo("Could not retrieve team external groups")); } /** - * Test fetch empty child teams. + * Test get external groups from team that cannot be externally managed. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testFetchEmptyChildTeams() throws IOException { - String teamSlug = "simple-team"; + public void testGetExternalGroupsTeamCannotBeExternallyManaged() throws IOException { + String teamSlug = "acme-developers"; GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHTeam team = org.getTeamBySlug(teamSlug); - Set result = team.listChildTeams().toSet(); - assertThat(result, is(empty())); + final GHIOException failure = assertThrows(GHTeamCannotBeExternallyManagedException.class, + () -> team.getExternalGroups()); + assertThat(failure.getMessage(), equalTo("Could not retrieve team external groups")); } /** - * Test get external groups. + * Test connect to external group by id. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetExternalGroups() throws IOException { + public void testConnectToExternalGroupById() throws IOException { String teamSlug = "acme-developers"; GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHTeam team = org.getTeamBySlug(teamSlug); - final List groups = team.getExternalGroups(); - assertThat(groups, notNullValue()); - assertThat(groups.size(), equalTo(1)); - assertThat(groupSummary(groups), hasItems("467431:acme-developers")); + final GHExternalGroup group = team.connectToExternalGroup(467431); - groups.forEach(group -> assertThat(group, isExternalGroupSummary())); + assertThat(group.getId(), equalTo(467431L)); + assertThat(group.getName(), equalTo("acme-developers")); + assertThat(group.getUpdatedAt(), notNullValue()); + + assertThat(group.getMembers(), notNullValue()); + assertThat(membersSummary(group), + hasItems("158311279:john-doe_acme:John Doe:john.doe@acme.corp", + "166731041:jane-doe_acme:Jane Doe:jane.doe@acme.corp")); + + assertThat(group.getTeams(), notNullValue()); + assertThat(teamSummary(group), hasItems("34519919:ACME-DEVELOPERS")); } /** - * Test get external groups from not enterprise managed organization. + * Test fail to connect to external group from other organization. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetExternalGroupsNotEnterpriseManagedOrganization() throws IOException { + public void testConnectToExternalGroupByGroup() throws IOException { String teamSlug = "acme-developers"; GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHTeam team = org.getTeamBySlug(teamSlug); + GHExternalGroup group = org.getExternalGroup(467431); - final GHIOException failure = assertThrows(GHNotExternallyManagedEnterpriseException.class, - () -> team.getExternalGroups()); - assertThat(failure.getMessage(), equalTo("Could not retrieve team external groups")); + GHExternalGroup connectedGroup = team.connectToExternalGroup(group); + + assertThat(connectedGroup.getId(), equalTo(467431L)); + assertThat(connectedGroup.getName(), equalTo("acme-developers")); + assertThat(connectedGroup.getUpdatedAt(), notNullValue()); + + assertThat(connectedGroup.getMembers(), notNullValue()); + assertThat(membersSummary(connectedGroup), + hasItems("158311279:john-doe_acme:John Doe:john.doe@acme.corp", + "166731041:jane-doe_acme:Jane Doe:jane.doe@acme.corp")); + + assertThat(group.getTeams(), notNullValue()); + assertThat(teamSummary(connectedGroup), hasItems("34519919:ACME-DEVELOPERS")); } /** - * Test get external groups from team that cannot be externally managed. + * Test failure when connecting to external group by id. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGetExternalGroupsTeamCannotBeExternallyManaged() throws IOException { + public void testFailConnectToExternalGroupWhenTeamHasMembers() throws IOException { String teamSlug = "acme-developers"; GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHTeam team = org.getTeamBySlug(teamSlug); final GHIOException failure = assertThrows(GHTeamCannotBeExternallyManagedException.class, - () -> team.getExternalGroups()); - assertThat(failure.getMessage(), equalTo("Could not retrieve team external groups")); + () -> team.connectToExternalGroup(467431)); + assertThat(failure.getMessage(), equalTo("Could not connect team to external group")); } /** - * Test set description. + * Test failure when connecting to external group by id. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testSetDescription() throws IOException { - - String description = "Updated by API Test"; - String teamSlug = "dummy-team"; - - // Set the description. - GHTeam team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); - assertThat(team.getHtmlUrl(), notNullValue()); - team.setDescription(description); - - // Check that it was set correctly. - team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); - assertThat(team.getDescription(), equalTo(description)); - - description += "Modified"; + public void testFailConnectToExternalGroupTeamIsNotAvailableInOrg() throws IOException { + String teamSlug = "acme-developers"; - // Set the description. - team.setDescription(description); + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHTeam team = org.getTeamBySlug(teamSlug); - // Check that it was set correctly. - team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); - assertThat(team.getDescription(), equalTo(description)); + assertThrows(GHFileNotFoundException.class, () -> team.connectToExternalGroup(12345)); } /** - * Test set privacy. + * Test delete connection to external group * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testSetPrivacy() throws IOException { - // we need to use a team that doesn't have child teams - // as secret privacy is not supported for parent teams - String teamSlug = "simple-team"; - Privacy privacy = Privacy.CLOSED; - - // Set the privacy. - GHTeam team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); - team.setPrivacy(privacy); - - // Check that it was set correctly. - team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); - assertThat(team.getPrivacy(), equalTo(privacy)); + public void testDeleteExternalGroupConnection() throws IOException { + String teamSlug = "acme-developers"; - privacy = Privacy.SECRET; + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHTeam team = org.getTeamBySlug(teamSlug); - // Set the privacy. - team.setPrivacy(privacy); + team.deleteExternalGroupConnection(); - // Check that it was set correctly. - team = gitHub.getOrganization(GITHUB_API_TEST_ORG).getTeamBySlug(teamSlug); - assertThat(team.getPrivacy(), equalTo(privacy)); + mockGitHub.apiServer() + .verify(1, + deleteRequestedFor(urlPathEqualTo("/orgs/" + team.getOrganization().getLogin() + "/teams/" + + team.getSlug() + "/external-groups"))); } } diff --git a/src/test/java/org/kohsuke/github/GHTreeBuilderTest.java b/src/test/java/org/kohsuke/github/GHTreeBuilderTest.java index 0d0ea02d3a..2f3ea77fb4 100644 --- a/src/test/java/org/kohsuke/github/GHTreeBuilderTest.java +++ b/src/test/java/org/kohsuke/github/GHTreeBuilderTest.java @@ -16,29 +16,29 @@ */ public class GHTreeBuilderTest extends AbstractGitHubWireMockTest { - private static byte[] CONTENT_DATA1 = { 0x01, 0x02, 0x03 }; + /** + * Create default GHTreeBuilderTest instance + */ + public GHTreeBuilderTest() { + } - private static byte[] CONTENT_DATA2 = { 0x04, 0x05, 0x06, 0x07 }; + private static String REPO_NAME = "hub4j-test-org/GHTreeBuilderTest"; - private static String CONTENT_README = "Thanks for using our application!\n"; + private static String PATH_SCRIPT = "app/run.sh"; private static String CONTENT_SCRIPT = "#!/bin/bash\necho Hello\n"; - private static String PATH_DATA1 = "data/val1.dat"; - private static String PATH_DATA2 = "data/val2.dat"; - private static String PATH_README = "doc/readme.txt"; - private static String PATH_SCRIPT = "app/run.sh"; + private static String CONTENT_README = "Thanks for using our application!\n"; - private static String REPO_NAME = "hub4j-test-org/GHTreeBuilderTest"; - private GHRef mainRef; + private static String PATH_DATA1 = "data/val1.dat"; + private static byte[] CONTENT_DATA1 = { 0x01, 0x02, 0x03 }; + + private static String PATH_DATA2 = "data/val2.dat"; + private static byte[] CONTENT_DATA2 = { 0x04, 0x05, 0x06, 0x07 }; private GHRepository repo; + private GHRef mainRef; private GHTreeBuilder treeBuilder; - /** - * Create default GHTreeBuilderTest instance - */ - public GHTreeBuilderTest() { - } /** * Cleanup. @@ -142,13 +142,6 @@ public void testDelete() throws Exception { } } - private long getFileSize(String path) throws IOException { - GHContent content = repo.getFileContent(path); - if (content == null) - throw new IOException("File not found: " + path); - return content.getSize(); - } - private GHCommit updateTree() throws IOException { String treeSha = treeBuilder.create().getSha(); GHCommit commit = new GHCommitBuilder(repo).message("Add files") @@ -162,4 +155,11 @@ private GHCommit updateTree() throws IOException { mainRef.updateTo(commitSha); return commit; } + + private long getFileSize(String path) throws IOException { + GHContent content = repo.getFileContent(path); + if (content == null) + throw new IOException("File not found: " + path); + return content.getSize(); + } } diff --git a/src/test/java/org/kohsuke/github/GHUserTest.java b/src/test/java/org/kohsuke/github/GHUserTest.java index adeaa294e8..bf47fb252e 100644 --- a/src/test/java/org/kohsuke/github/GHUserTest.java +++ b/src/test/java/org/kohsuke/github/GHUserTest.java @@ -27,28 +27,52 @@ public GHUserTest() { } /** - * Creates the and count private repos. + * Checks if is member of. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void createAndCountPrivateRepos() throws IOException { - String login = gitHub.getMyself().getLogin(); + public void isMemberOf() throws IOException { + GHUser u = gitHub.getUser("bitwiseman"); + String teamSlug = "dummy-team"; + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHTeam team = org.getTeamBySlug(teamSlug); - GHRepository repository = gitHub.createRepository("github-user-test-private-repo") - .description("a test private repository used to test kohsuke's github-api") - .homepage("http://github-api.kohsuke.org/") - .private_(true) - .create(); + assertThat(u.isMemberOf(org), is(true)); + assertThat(u.isMemberOf(team), is(true)); + assertThat(u.isPublicMemberOf(org), is(false)); - try { - assertThat(repository, notNullValue()); - GHUser ghUser = gitHub.getUser(login); - assertThat(ghUser.getTotalPrivateRepoCount().orElse(-1), greaterThan(0)); - } finally { - repository.delete(); + org = gitHub.getOrganization("hub4j"); + assertThat(u.isMemberOf(org), is(true)); + assertThat(u.isPublicMemberOf(org), is(true)); + + u = gitHub.getUser("rtyler"); + assertThat(u.isMemberOf(org), is(false)); + assertThat(u.isMemberOf(team), is(false)); + assertThat(u.isPublicMemberOf(org), is(false)); + } + + /** + * List follows and followers. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void listFollowsAndFollowers() throws IOException { + GHUser u = gitHub.getUser("rtyler"); + assertThat(count30(u.listFollows()), not(count30(u.listFollowers()))); + } + + private Set count30(PagedIterable l) { + Set users = new HashSet(); + PagedIterator itr = l.iterator(); + for (int i = 0; i < 30 && itr.hasNext(); i++) { + users.add(itr.next()); } + assertThat(users.size(), equalTo(30)); + return users; } /** @@ -94,42 +118,25 @@ public int compare(GHKey ghKey, GHKey t1) { } /** - * Checks if is member of. + * List public repositories. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void isMemberOf() throws IOException { - GHUser u = gitHub.getUser("bitwiseman"); - String teamSlug = "dummy-team"; - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHTeam team = org.getTeamBySlug(teamSlug); - - assertThat(u.isMemberOf(org), is(true)); - assertThat(u.isMemberOf(team), is(true)); - assertThat(u.isPublicMemberOf(org), is(false)); - - org = gitHub.getOrganization("hub4j"); - assertThat(u.isMemberOf(org), is(true)); - assertThat(u.isPublicMemberOf(org), is(true)); - - u = gitHub.getUser("rtyler"); - assertThat(u.isMemberOf(org), is(false)); - assertThat(u.isMemberOf(team), is(false)); - assertThat(u.isPublicMemberOf(org), is(false)); - } + public void listPublicRepositories() throws IOException { + GHUser user = gitHub.getUser("kohsuke"); + Iterator itr = user.listRepositories().iterator(); + int i = 0; + for (; i < 115; i++) { + assertThat(itr.hasNext(), is(true)); + GHRepository r = itr.next(); + // System.out.println(r.getFullName()); + assertThat(r.getUrl(), notNullValue()); + assertThat(r.getId(), not(0L)); + } - /** - * List follows and followers. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void listFollowsAndFollowers() throws IOException { - GHUser u = gitHub.getUser("rtyler"); - assertThat(count30(u.listFollows()), not(count30(u.listFollowers()))); + assertThat(i, equalTo(115)); } /** @@ -150,15 +157,15 @@ public void listProjects() throws IOException { } /** - * List public repositories. + * List public repositories page size 62. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void listPublicRepositories() throws IOException { + public void listPublicRepositoriesPageSize62() throws IOException { GHUser user = gitHub.getUser("kohsuke"); - Iterator itr = user.listRepositories().iterator(); + Iterator itr = user.listRepositories(62).iterator(); int i = 0; for (; i < 115; i++) { assertThat(itr.hasNext(), is(true)); @@ -172,25 +179,28 @@ public void listPublicRepositories() throws IOException { } /** - * List public repositories page size 62. + * Creates the and count private repos. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void listPublicRepositoriesPageSize62() throws IOException { - GHUser user = gitHub.getUser("kohsuke"); - Iterator itr = user.listRepositories(62).iterator(); - int i = 0; - for (; i < 115; i++) { - assertThat(itr.hasNext(), is(true)); - GHRepository r = itr.next(); - // System.out.println(r.getFullName()); - assertThat(r.getUrl(), notNullValue()); - assertThat(r.getId(), not(0L)); - } + public void createAndCountPrivateRepos() throws IOException { + String login = gitHub.getMyself().getLogin(); - assertThat(i, equalTo(115)); + GHRepository repository = gitHub.createRepository("github-user-test-private-repo") + .description("a test private repository used to test kohsuke's github-api") + .homepage("http://github-api.kohsuke.org/") + .private_(true) + .create(); + + try { + assertThat(repository, notNullValue()); + GHUser ghUser = gitHub.getUser(login); + assertThat(ghUser.getTotalPrivateRepoCount().orElse(-1), greaterThan(0)); + } finally { + repository.delete(); + } } /** @@ -204,15 +214,13 @@ public void verifyBioAndHireable() throws IOException { GHUser u = gitHub.getUser("Chew"); assertThat(u.getBio(), equalTo("I like to program things and I hope to program something cool one day :D")); assertThat(u.isHireable(), is(true)); - assertThat(u.getTwitterUsername(), equalTo("ChewCraft")); + assertThat(u.getTwitterUsername(), notNullValue()); assertThat(u.getBlog(), equalTo("https://chew.pw")); assertThat(u.getCompany(), equalTo("@Memerator")); assertThat(u.getFollowersCount(), equalTo(29)); assertThat(u.getFollowingCount(), equalTo(3)); assertThat(u.getPublicGistCount(), equalTo(4)); assertThat(u.getPublicRepoCount(), equalTo(96)); - assertThat(u.getCreatedAt(), equalTo(GitHubClient.parseInstant("2014-07-26T23:41:36Z"))); - assertThat(u.getUpdatedAt(), equalTo(GitHubClient.parseInstant("2020-06-06T20:16:06Z"))); } /** @@ -239,17 +247,7 @@ public void verifySuspendedAt() throws IOException { assertThat(normal.getSuspendedAt(), is(nullValue())); GHUser suspended = gitHub.getUser("suspended"); - Instant suspendedAt = Instant.ofEpochMilli(Instant.parse("2024-08-08T00:00:00Z").toEpochMilli()); + Date suspendedAt = new Date(Instant.parse("2024-08-08T00:00:00Z").toEpochMilli()); assertThat(suspended.getSuspendedAt(), equalTo(suspendedAt)); } - - private Set count30(PagedIterable l) { - Set users = new HashSet(); - PagedIterator itr = l.iterator(); - for (int i = 0; i < 30 && itr.hasNext(); i++) { - users.add(itr.next()); - } - assertThat(users.size(), equalTo(30)); - return users; - } } diff --git a/src/test/java/org/kohsuke/github/GHVerificationReasonTest.java b/src/test/java/org/kohsuke/github/GHVerificationReasonTest.java index 5a9b5205af..3573fd3860 100644 --- a/src/test/java/org/kohsuke/github/GHVerificationReasonTest.java +++ b/src/test/java/org/kohsuke/github/GHVerificationReasonTest.java @@ -19,292 +19,292 @@ public GHVerificationReasonTest() { } /** - * Test bad cert. + * Test expired key. * * @throws Exception * the exception */ + // Issue 737 @Test - public void testBadCert() throws Exception { + public void testExpiredKey() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); - assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.BAD_CERT)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), + equalTo(GHVerification.Reason.EXPIRED_KEY)); } /** - * Test bad email. + * Test not signing key. * * @throws Exception * the exception */ @Test - public void testBadEmail() throws Exception { + public void testNotSigningKey() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f09"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f02"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.BAD_EMAIL)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), + equalTo(GHVerification.Reason.NOT_SIGNING_KEY)); } /** - * Test expired key. + * Test gpgverify error. * * @throws Exception * the exception */ - // Issue 737 @Test - public void testExpiredKey() throws Exception { + public void testGpgverifyError() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f03"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.EXPIRED_KEY)); + equalTo(GHVerification.Reason.GPGVERIFY_ERROR)); } /** - * Test gpgverify error. + * Test gpgverify unavailable. * * @throws Exception * the exception */ @Test - public void testGpgverifyError() throws Exception { + public void testGpgverifyUnavailable() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f03"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f04"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.GPGVERIFY_ERROR)); + equalTo(GHVerification.Reason.GPGVERIFY_UNAVAILABLE)); } /** - * Test gpgverify unavailable. + * Test unsigned. * * @throws Exception * the exception */ @Test - public void testGpgverifyUnavailable() throws Exception { + public void testUnsigned() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f04"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f05"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.GPGVERIFY_UNAVAILABLE)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.UNSIGNED)); } /** - * Test invalid. + * Test unknown signature type. * * @throws Exception * the exception */ @Test - public void testInvalid() throws Exception { + public void testUnknownSignatureType() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f12"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f06"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.INVALID)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), + equalTo(GHVerification.Reason.UNKNOWN_SIGNATURE_TYPE)); } /** - * Test malformed sig. + * Test no user. * * @throws Exception * the exception */ @Test - public void testMalformedSig() throws Exception { + public void testNoUser() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f07"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); - assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.MALFORMED_SIG)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.NO_USER)); } /** - * Test malformed signature. + * Test unverified email. * * @throws Exception * the exception */ @Test - public void testMalformedSignature() throws Exception { + public void testUnverifiedEmail() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f11"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f08"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.MALFORMED_SIGNATURE)); + equalTo(GHVerification.Reason.UNVERIFIED_EMAIL)); } /** - * Test no user. + * Test bad email. * * @throws Exception * the exception */ @Test - public void testNoUser() throws Exception { + public void testBadEmail() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f07"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f09"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.NO_USER)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.BAD_EMAIL)); } /** - * Test not signing key. + * Test unknown key. * * @throws Exception * the exception */ @Test - public void testNotSigningKey() throws Exception { + public void testUnknownKey() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f02"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f10"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.NOT_SIGNING_KEY)); + equalTo(GHVerification.Reason.UNKNOWN_KEY)); } /** - * Test OSCP error. + * Test malformed signature. * * @throws Exception * the exception */ @Test - public void testOcspError() throws Exception { + public void testMalformedSignature() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f11"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); - assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.OCSP_ERROR)); + equalTo(GHVerification.Reason.MALFORMED_SIGNATURE)); } /** - * Test OSCP pending. + * Test invalid. * * @throws Exception * the exception */ @Test - public void testOscpPending() throws Exception { + public void testInvalid() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f12"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); - assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.OCSP_PENDING)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.INVALID)); } /** - * Test OCSP revoked. + * Test valid. * * @throws Exception * the exception */ @Test - public void testOscpRevoked() throws Exception { + public void testValid() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f13"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); + assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(true)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.VALID)); + assertThat(commit.getCommitShortInfo().getVerification().getPayload(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); - assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.OCSP_REVOKED)); } /** - * Test unknown key. + * Test bad cert. * * @throws Exception * the exception */ @Test - public void testUnknownKey() throws Exception { + public void testBadCert() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f10"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); + assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.UNKNOWN_KEY)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.BAD_CERT)); } /** - * Test unknown signature type. + * Test malformed sig. * * @throws Exception * the exception */ @Test - public void testUnknownSignatureType() throws Exception { + public void testMalformedSig() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f06"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); + assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.UNKNOWN_SIGNATURE_TYPE)); + equalTo(GHVerification.Reason.MALFORMED_SIG)); } /** - * Test unsigned. + * Test OSCP error. * * @throws Exception * the exception */ @Test - public void testUnsigned() throws Exception { + public void testOcspError() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f05"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); + assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.UNSIGNED)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), + equalTo(GHVerification.Reason.OCSP_ERROR)); } /** - * Test unverified email. + * Test OSCP pending. * * @throws Exception * the exception */ @Test - public void testUnverifiedEmail() throws Exception { + public void testOscpPending() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f08"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); + assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); assertThat(commit.getCommitShortInfo().getVerification().getReason(), - equalTo(GHVerification.Reason.UNVERIFIED_EMAIL)); + equalTo(GHVerification.Reason.OCSP_PENDING)); } /** - * Test valid. + * Test OCSP revoked. * * @throws Exception * the exception */ @Test - public void testValid() throws Exception { + public void testOscpRevoked() throws Exception { GHRepository r = gitHub.getRepository("hub4j/github-api"); - GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f13"); + GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f01"); assertThat(commit.getCommitShortInfo().getAuthor().getName(), equalTo("Sourabh Parkala")); - assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(true)); - assertThat(commit.getCommitShortInfo().getVerification().getReason(), equalTo(GHVerification.Reason.VALID)); - assertThat(commit.getCommitShortInfo().getVerification().getPayload(), notNullValue()); assertThat(commit.getCommitShortInfo().getVerification().getSignature(), notNullValue()); + assertThat(commit.getCommitShortInfo().getVerification().isVerified(), is(false)); + assertThat(commit.getCommitShortInfo().getVerification().getReason(), + equalTo(GHVerification.Reason.OCSP_REVOKED)); } } diff --git a/src/test/java/org/kohsuke/github/GHWorkflowRunTest.java b/src/test/java/org/kohsuke/github/GHWorkflowRunTest.java index bacd783ab2..d15f506672 100644 --- a/src/test/java/org/kohsuke/github/GHWorkflowRunTest.java +++ b/src/test/java/org/kohsuke/github/GHWorkflowRunTest.java @@ -9,17 +9,15 @@ import org.kohsuke.github.GHWorkflowRun.Status; import org.kohsuke.github.function.InputStreamFunction; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Optional; import java.util.Scanner; import java.util.function.Function; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -32,177 +30,32 @@ */ public class GHWorkflowRunTest extends AbstractGitHubWireMockTest { - private static final String ARTIFACTS_WORKFLOW_NAME = "Artifacts workflow"; - - private static final String ARTIFACTS_WORKFLOW_PATH = "artifacts-workflow.yml"; - private static final String FAST_WORKFLOW_NAME = "Fast workflow"; - private static final String FAST_WORKFLOW_PATH = "fast-workflow.yml"; - - private static final String MAIN_BRANCH = "main"; - private static final String MULTI_JOBS_WORKFLOW_NAME = "Multi jobs workflow"; + /** + * Create default GHWorkflowRunTest instance + */ + public GHWorkflowRunTest() { + } - private static final String MULTI_JOBS_WORKFLOW_PATH = "multi-jobs-workflow.yml"; private static final String REPO_NAME = "hub4j-test-org/GHWorkflowRunTest"; - - private static final String RUN_A_ONE_LINE_SCRIPT_STEP_NAME = "Run a one-line script"; + private static final String MAIN_BRANCH = "main"; private static final String SECOND_BRANCH = "second-branch"; - private static final String SLOW_WORKFLOW_NAME = "Slow workflow"; - private static final String SLOW_WORKFLOW_PATH = "slow-workflow.yml"; - private static final String UBUNTU_LABEL = "ubuntu-latest"; - private static void checkArtifactProperties(GHArtifact artifact, String artifactName) throws IOException { - assertThat(artifact.getId(), notNullValue()); - assertThat(artifact.getNodeId(), notNullValue()); - assertThat(artifact.getRepository().getFullName(), equalTo(REPO_NAME)); - assertThat(artifact.getName(), is(artifactName)); - assertThat(artifact.getArchiveDownloadUrl().getPath(), containsString("actions/artifacts")); - assertThat(artifact.getCreatedAt(), notNullValue()); - assertThat(artifact.getUpdatedAt(), notNullValue()); - assertThat(artifact.getExpiresAt(), notNullValue()); - assertThat(artifact.getSizeInBytes(), greaterThan(0L)); - assertThat(artifact.isExpired(), is(false)); - } - - private static void checkJobProperties(long workflowRunId, GHWorkflowJob job, String jobName) { - assertThat(job.getId(), notNullValue()); - assertThat(job.getNodeId(), notNullValue()); - assertThat(job.getRepository().getFullName(), equalTo(REPO_NAME)); - assertThat(job.getName(), is(jobName)); - assertThat(job.getStartedAt(), notNullValue()); - assertThat(job.getCompletedAt(), notNullValue()); - assertThat(job.getHeadSha(), notNullValue()); - assertThat(job.getStatus(), is(Status.COMPLETED)); - assertThat(job.getConclusion(), is(Conclusion.SUCCESS)); - assertThat(job.getRunId(), is(workflowRunId)); - assertThat(job.getUrl().getPath(), containsString("/actions/jobs/")); - assertThat(job.getHtmlUrl().getPath(), containsString("/runs/" + job.getId())); - assertThat(job.getCheckRunUrl().getPath(), containsString("/check-runs/")); - assertThat(job.getRunnerId(), is(1)); - assertThat(job.getRunnerName(), containsString("my runner")); - assertThat(job.getRunnerGroupId(), is(2)); - assertThat(job.getRunnerGroupName(), containsString("my runner group")); - - // we only test the step we have control over, the others are added by GitHub - Optional step = job.getSteps() - .stream() - .filter(s -> RUN_A_ONE_LINE_SCRIPT_STEP_NAME.equals(s.getName())) - .findFirst(); - if (!step.isPresent()) { - fail("Unable to find " + RUN_A_ONE_LINE_SCRIPT_STEP_NAME + " step"); - } - - Optional labelOptional = job.getLabels().stream().filter(s -> s.equals(UBUNTU_LABEL)).findFirst(); - if (!labelOptional.isPresent()) { - fail("Unable to find " + UBUNTU_LABEL + " label"); - } - - checkStepProperties(step.get(), RUN_A_ONE_LINE_SCRIPT_STEP_NAME, 2); - } - - private static void checkStepProperties(Step step, String name, int number) { - assertThat(step.getName(), is(name)); - assertThat(step.getNumber(), is(number)); - assertThat(step.getStatus(), is(Status.COMPLETED)); - assertThat(step.getConclusion(), is(Conclusion.SUCCESS)); - assertThat(step.getStartedAt(), notNullValue()); - assertThat(step.getCompletedAt(), notNullValue()); - } - - @SuppressWarnings("resource") - private static InputStreamFunction getLogArchiveInputStreamFunction(String mainLogFileName, - List logsArchiveEntries) { - return (is) -> { - try (ZipInputStream zis = new ZipInputStream(is)) { - StringBuilder sb = new StringBuilder(); - - ZipEntry ze; - while ((ze = zis.getNextEntry()) != null) { - logsArchiveEntries.add(ze.getName()); - if (mainLogFileName.equals(ze.getName())) { - // the scanner has to be kept open to avoid closing zis - Scanner scanner = new Scanner(zis); - while (scanner.hasNextLine()) { - sb.append(scanner.nextLine()).append("\n"); - } - } - } - - return sb.toString(); - } - }; - } - - @SuppressWarnings("resource") - private static InputStreamFunction getLogTextInputStreamFunction() { - return (is) -> { - StringBuilder sb = new StringBuilder(); - Scanner scanner = new Scanner(is); - while (scanner.hasNextLine()) { - sb.append(scanner.nextLine()).append("\n"); - } - return sb.toString(); - }; - } - - private static Optional getWorkflowRun(GHRepository repository, - String workflowName, - String branch, - Conclusion conclusion) { - List workflowRuns = repository.queryWorkflowRuns() - .branch(branch) - .conclusion(conclusion) - .event(GHEvent.PULL_REQUEST) - .list() - .withPageSize(20) - .iterator() - .nextPage(); - - for (GHWorkflowRun workflowRun : workflowRuns) { - if (workflowRun.getName().equals(workflowName)) { - return Optional.of(workflowRun); - } - } - return Optional.empty(); - } + private static final String FAST_WORKFLOW_PATH = "fast-workflow.yml"; + private static final String FAST_WORKFLOW_NAME = "Fast workflow"; - private static Optional getWorkflowRun(GHRepository repository, - String workflowName, - String branch, - Status status, - long latestPreexistingWorkflowRunId) { - List workflowRuns = repository.queryWorkflowRuns() - .branch(branch) - .status(status) - .event(GHEvent.WORKFLOW_DISPATCH) - .list() - .withPageSize(20) - .iterator() - .nextPage(); + private static final String SLOW_WORKFLOW_PATH = "slow-workflow.yml"; + private static final String SLOW_WORKFLOW_NAME = "Slow workflow"; - for (GHWorkflowRun workflowRun : workflowRuns) { - if (workflowRun.getName().equals(workflowName) && workflowRun.getId() > latestPreexistingWorkflowRunId) { - return Optional.of(workflowRun); - } - } - return Optional.empty(); - } + private static final String ARTIFACTS_WORKFLOW_PATH = "artifacts-workflow.yml"; + private static final String ARTIFACTS_WORKFLOW_NAME = "Artifacts workflow"; - private static Status getWorkflowRunStatus(GHRepository repository, long workflowRunId) { - try { - return repository.getWorkflowRun(workflowRunId).getStatus(); - } catch (IOException e) { - throw new IllegalStateException("Unable to get workflow run status", e); - } - } + private static final String MULTI_JOBS_WORKFLOW_PATH = "multi-jobs-workflow.yml"; + private static final String MULTI_JOBS_WORKFLOW_NAME = "Multi jobs workflow"; + private static final String RUN_A_ONE_LINE_SCRIPT_STEP_NAME = "Run a one-line script"; + private static final String UBUNTU_LABEL = "ubuntu-latest"; private GHRepository repo; - /** - * Create default GHWorkflowRunTest instance - */ - public GHWorkflowRunTest() { - } - /** * Sets the up. * @@ -215,159 +68,55 @@ public void setUp() throws Exception { } /** - * Test approval. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testApproval() throws IOException { - List pullRequests = repo.queryPullRequests() - .base(MAIN_BRANCH) - .sort(Sort.CREATED) - .direction(GHDirection.DESC) - .state(GHIssueState.OPEN) - .list() - .toList(); - - assertThat(pullRequests.size(), greaterThanOrEqualTo(1)); - GHPullRequest pullRequest = pullRequests.get(0); - - await("Waiting for workflow run to be pending", - (nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, - FAST_WORKFLOW_NAME, - MAIN_BRANCH, - Conclusion.ACTION_REQUIRED).isPresent()); - - GHWorkflowRun workflowRun = getWorkflowRun(FAST_WORKFLOW_NAME, MAIN_BRANCH, Conclusion.ACTION_REQUIRED) - .orElseThrow(() -> new IllegalStateException("We must have a valid workflow run starting from here")); - - workflowRun.approve(); - - await("Waiting for workflow run to be approved", - (nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, - FAST_WORKFLOW_NAME, - pullRequest.getHead().getRef(), - Conclusion.SUCCESS).isPresent()); - - workflowRun = repo.getWorkflowRun(workflowRun.getId()); - - assertThat(workflowRun.getConclusion(), is(Conclusion.SUCCESS)); - } - - /** - * Test artifacts. + * Test manual run and basic information. * * @throws IOException * Signals that an I/O exception has occurred. */ - @SuppressWarnings("resource") @Test - public void testArtifacts() throws IOException { - // Recorded with Authorization, then manually updated - snapshotNotAllowed(); - - mockGitHub.customizeRecordSpec(recordSpecBuilder -> recordSpecBuilder.captureHeader("Authorization")); - GHWorkflow workflow = repo.getWorkflow(ARTIFACTS_WORKFLOW_PATH); + public void testManualRunAndBasicInformation() throws IOException { + GHWorkflow workflow = repo.getWorkflow(FAST_WORKFLOW_PATH); long latestPreexistingWorkflowRunId = getLatestPreexistingWorkflowRunId(); workflow.dispatch(MAIN_BRANCH); await((nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, - ARTIFACTS_WORKFLOW_NAME, + FAST_WORKFLOW_NAME, MAIN_BRANCH, Status.COMPLETED, latestPreexistingWorkflowRunId).isPresent()); - GHWorkflowRun workflowRun = getWorkflowRun(ARTIFACTS_WORKFLOW_NAME, + GHWorkflowRun workflowRun = getWorkflowRun(FAST_WORKFLOW_NAME, MAIN_BRANCH, Status.COMPLETED, latestPreexistingWorkflowRunId) .orElseThrow(() -> new IllegalStateException("We must have a valid workflow run starting from here")); - List artifacts = new ArrayList<>(workflowRun.listArtifacts().toList()); - artifacts.sort((a1, a2) -> a1.getName().compareTo(a2.getName())); - - assertThat(artifacts.size(), is(2)); - - // Test properties - checkArtifactProperties(artifacts.get(0), "artifact1"); - checkArtifactProperties(artifacts.get(1), "artifact2"); - - Logger clientLogger = Logger.getLogger(GitHubClient.class.getName()); - - // Test download from upload-artifact@v3 infrastructure - String artifactContent = artifacts.get(0).download((is) -> { - // At finest log level, all body responses are byte arrays. - if (clientLogger.getLevel() != Level.FINEST) { - assertThat(is, not(isA(ByteArrayInputStream.class))); - } - try (ZipInputStream zis = new ZipInputStream(is)) { - StringBuilder sb = new StringBuilder(); - - ZipEntry ze = zis.getNextEntry(); - assertThat(ze.getName(), is("artifact1.txt")); - - // the scanner has to be kept open to avoid closing zis - Scanner scanner = new Scanner(zis); - while (scanner.hasNextLine()) { - sb.append(scanner.nextLine()); - } - - return sb.toString(); - } - }); - - // Test download from upload-artifact@v4 infrastructure - artifactContent = artifacts.get(1).download((is) -> { - try (ZipInputStream zis = new ZipInputStream(is)) { - StringBuilder sb = new StringBuilder(); - - ZipEntry ze = zis.getNextEntry(); - assertThat(ze.getName(), is("artifact2.txt")); - - // the scanner has to be kept open to avoid closing zis - Scanner scanner = new Scanner(zis); - while (scanner.hasNextLine()) { - sb.append(scanner.nextLine()); - } - - return sb.toString(); - } - }); - - assertThat(artifactContent, is("artifact2")); - - // Test GHRepository#getArtifact(long) as we are sure we have artifacts around - GHArtifact artifactById = repo.getArtifact(artifacts.get(0).getId()); - checkArtifactProperties(artifactById, "artifact1"); - - artifactById = repo.getArtifact(artifacts.get(1).getId()); - checkArtifactProperties(artifactById, "artifact2"); - - // Test GHRepository#listArtifacts() as we are sure we have artifacts around - List artifactsFromRepo = new ArrayList<>( - repo.listArtifacts().withPageSize(2).iterator().nextPage()); - artifactsFromRepo.sort((a1, a2) -> a1.getName().compareTo(a2.getName())); - - // We have at least the two artifacts we just added - assertThat(artifactsFromRepo.size(), is(2)); - - // Test properties - checkArtifactProperties(artifactsFromRepo.get(0), "artifact1"); - checkArtifactProperties(artifactsFromRepo.get(1), "artifact2"); - - // Now let's test the delete() method - GHArtifact artifact1 = artifacts.get(0); - artifact1.delete(); - - try { - repo.getArtifact(artifact1.getId()); - fail("Getting the artifact should fail as it was deleted"); - } catch (GHFileNotFoundException e) { - assertThat(e.getMessage(), containsString("Not Found")); - } + assertThat(workflowRun.getWorkflowId(), equalTo(workflow.getId())); + assertThat(workflowRun.getId(), notNullValue()); + assertThat(workflowRun.getNodeId(), notNullValue()); + assertThat(workflowRun.getRepository().getFullName(), equalTo(REPO_NAME)); + assertThat(workflowRun.getUrl().getPath(), containsString("/actions/runs/")); + assertThat(workflowRun.getHtmlUrl().getPath(), containsString("/actions/runs/")); + assertThat(workflowRun.getJobsUrl().getPath(), endsWith("/jobs")); + assertThat(workflowRun.getLogsUrl().getPath(), endsWith("/logs")); + assertThat(workflowRun.getCheckSuiteUrl().getPath(), containsString("/check-suites/")); + assertThat(workflowRun.getArtifactsUrl().getPath(), endsWith("/artifacts")); + assertThat(workflowRun.getCancelUrl().getPath(), endsWith("/cancel")); + assertThat(workflowRun.getRerunUrl().getPath(), endsWith("/rerun")); + assertThat(workflowRun.getWorkflowUrl().getPath(), containsString("/actions/workflows/")); + assertThat(workflowRun.getHeadBranch(), equalTo(MAIN_BRANCH)); + assertThat(workflowRun.getHeadCommit().getId(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getTreeId(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getMessage(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getTimestamp(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getAuthor().getEmail(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getCommitter().getEmail(), notNullValue()); + assertThat(workflowRun.getEvent(), equalTo(GHEvent.WORKFLOW_DISPATCH)); + assertThat(workflowRun.getStatus(), equalTo(Status.COMPLETED)); + assertThat(workflowRun.getConclusion(), equalTo(Conclusion.SUCCESS)); + assertThat(workflowRun.getHeadSha(), notNullValue()); } /** @@ -459,56 +208,105 @@ public void testDelete() throws IOException { } /** - * Test jobs. + * Test search on branch. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testJobs() throws IOException { - GHWorkflow workflow = repo.getWorkflow(MULTI_JOBS_WORKFLOW_PATH); + public void testSearchOnBranch() throws IOException { + GHWorkflow workflow = repo.getWorkflow(FAST_WORKFLOW_PATH); long latestPreexistingWorkflowRunId = getLatestPreexistingWorkflowRunId(); - workflow.dispatch(MAIN_BRANCH); + workflow.dispatch(SECOND_BRANCH); await((nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, - MULTI_JOBS_WORKFLOW_NAME, - MAIN_BRANCH, + FAST_WORKFLOW_NAME, + SECOND_BRANCH, Status.COMPLETED, latestPreexistingWorkflowRunId).isPresent()); - GHWorkflowRun workflowRun = getWorkflowRun(MULTI_JOBS_WORKFLOW_NAME, - MAIN_BRANCH, + GHWorkflowRun workflowRun = getWorkflowRun(FAST_WORKFLOW_NAME, + SECOND_BRANCH, Status.COMPLETED, latestPreexistingWorkflowRunId) .orElseThrow(() -> new IllegalStateException("We must have a valid workflow run starting from here")); - List jobs = workflowRun.listJobs() - .toList() - .stream() - .sorted((j1, j2) -> j1.getName().compareTo(j2.getName())) - .collect(Collectors.toList()); + assertThat(workflowRun.getWorkflowId(), equalTo(workflow.getId())); + assertThat(workflowRun.getHeadBranch(), equalTo(SECOND_BRANCH)); + assertThat(workflowRun.getEvent(), equalTo(GHEvent.WORKFLOW_DISPATCH)); + assertThat(workflowRun.getStatus(), equalTo(Status.COMPLETED)); + assertThat(workflowRun.getConclusion(), equalTo(Conclusion.SUCCESS)); + } - assertThat(jobs.size(), is(2)); + /** + * Test search on created and head sha. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testSearchOnCreatedAndHeadSha() throws IOException { + GHWorkflow workflow = repo.getWorkflow(FAST_WORKFLOW_PATH); - GHWorkflowJob job1 = jobs.get(0); - checkJobProperties(workflowRun.getId(), job1, "job1"); - String fullLogContent = job1.downloadLogs(getLogTextInputStreamFunction()); - assertThat(fullLogContent, containsString("Hello from job1!")); + long latestPreexistingWorkflowRunId = getLatestPreexistingWorkflowRunId(); - GHWorkflowJob job2 = jobs.get(1); - checkJobProperties(workflowRun.getId(), job2, "job2"); - fullLogContent = job2.downloadLogs(getLogTextInputStreamFunction()); - assertThat(fullLogContent, containsString("Hello from job2!")); + Instant before = Instant.parse("2024-02-09T10:19:00.00Z"); - // while we have a job around, test GHRepository#getWorkflowJob(id) - GHWorkflowJob job1ById = repo.getWorkflowJob(job1.getId()); - checkJobProperties(workflowRun.getId(), job1ById, "job1"); + String mainBranchHeadSha = repo.getBranch(MAIN_BRANCH).getSHA1(); + String secondBranchHeadSha = repo.getBranch(SECOND_BRANCH).getSHA1(); - // Also test listAllJobs() works correctly - List allJobs = workflowRun.listAllJobs().withPageSize(10).iterator().nextPage(); - assertThat(allJobs.size(), greaterThanOrEqualTo(2)); + workflow.dispatch(MAIN_BRANCH); + workflow.dispatch(SECOND_BRANCH); + + await((nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, + FAST_WORKFLOW_NAME, + MAIN_BRANCH, + Status.COMPLETED, + latestPreexistingWorkflowRunId).isPresent()); + await((nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, + FAST_WORKFLOW_NAME, + SECOND_BRANCH, + Status.COMPLETED, + latestPreexistingWorkflowRunId).isPresent()); + + List mainBranchHeadShaWorkflowRuns = repo.queryWorkflowRuns() + .headSha(mainBranchHeadSha) + .created(">=" + before.toString()) + .list() + .toList(); + List secondBranchHeadShaWorkflowRuns = repo.queryWorkflowRuns() + .headSha(secondBranchHeadSha) + .created(">=" + before.toString()) + .list() + .toList(); + + assertThat(mainBranchHeadShaWorkflowRuns, hasSize(greaterThanOrEqualTo(1))); + assertThat(mainBranchHeadShaWorkflowRuns, everyItem(hasProperty("headSha", equalTo(mainBranchHeadSha)))); + // Ideally, we would use everyItem() but the bridge method is in the way + for (GHWorkflowRun workflowRun : mainBranchHeadShaWorkflowRuns) { + assertThat(workflowRun.getCreatedAt(), greaterThanOrEqualTo(Date.from(before))); + } + + assertThat(secondBranchHeadShaWorkflowRuns, hasSize(greaterThanOrEqualTo(1))); + assertThat(secondBranchHeadShaWorkflowRuns, everyItem(hasProperty("headSha", equalTo(secondBranchHeadSha)))); + // Ideally, we would use everyItem() but the bridge method is in the way + for (GHWorkflowRun workflowRun : secondBranchHeadShaWorkflowRuns) { + assertThat(workflowRun.getCreatedAt(), greaterThanOrEqualTo(Date.from(before))); + } + + List mainBranchHeadShaWorkflowRunsBefore = repo.queryWorkflowRuns() + .headSha(repo.getBranch(MAIN_BRANCH).getSHA1()) + .created("<" + before.toString()) + .list() + .toList(); + // Ideally, we would use that but the bridge method is causing issues + // assertThat(mainBranchHeadShaWorkflowRunsBefore, everyItem(hasProperty("createdAt", + // lessThan(Date.from(before))))); + for (GHWorkflowRun workflowRun : mainBranchHeadShaWorkflowRunsBefore) { + assertThat(workflowRun.getCreatedAt(), lessThan(Date.from(before))); + } } /** @@ -555,158 +353,206 @@ public void testLogs() throws IOException { } /** - * Test manual run and basic information. + * Test artifacts. * * @throws IOException * Signals that an I/O exception has occurred. */ + @SuppressWarnings("resource") @Test - public void testManualRunAndBasicInformation() throws IOException { - GHWorkflow workflow = repo.getWorkflow(FAST_WORKFLOW_PATH); + public void testArtifacts() throws IOException { + // Recorded with Authorization, then manually updated + snapshotNotAllowed(); + + mockGitHub.customizeRecordSpec(recordSpecBuilder -> recordSpecBuilder.captureHeader("Authorization")); + GHWorkflow workflow = repo.getWorkflow(ARTIFACTS_WORKFLOW_PATH); long latestPreexistingWorkflowRunId = getLatestPreexistingWorkflowRunId(); workflow.dispatch(MAIN_BRANCH); await((nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, - FAST_WORKFLOW_NAME, + ARTIFACTS_WORKFLOW_NAME, MAIN_BRANCH, Status.COMPLETED, latestPreexistingWorkflowRunId).isPresent()); - GHWorkflowRun workflowRun = getWorkflowRun(FAST_WORKFLOW_NAME, + GHWorkflowRun workflowRun = getWorkflowRun(ARTIFACTS_WORKFLOW_NAME, MAIN_BRANCH, Status.COMPLETED, latestPreexistingWorkflowRunId) .orElseThrow(() -> new IllegalStateException("We must have a valid workflow run starting from here")); - assertThat(workflowRun.getWorkflowId(), equalTo(workflow.getId())); - assertThat(workflowRun.getId(), notNullValue()); - assertThat(workflowRun.getNodeId(), notNullValue()); - assertThat(workflowRun.getRepository().getFullName(), equalTo(REPO_NAME)); - assertThat(workflowRun.getUrl().getPath(), containsString("/actions/runs/")); - assertThat(workflowRun.getHtmlUrl().getPath(), containsString("/actions/runs/")); - assertThat(workflowRun.getJobsUrl().getPath(), endsWith("/jobs")); - assertThat(workflowRun.getLogsUrl().getPath(), endsWith("/logs")); - assertThat(workflowRun.getCheckSuiteUrl().getPath(), containsString("/check-suites/")); - assertThat(workflowRun.getArtifactsUrl().getPath(), endsWith("/artifacts")); - assertThat(workflowRun.getCancelUrl().getPath(), endsWith("/cancel")); - assertThat(workflowRun.getRerunUrl().getPath(), endsWith("/rerun")); - assertThat(workflowRun.getWorkflowUrl().getPath(), containsString("/actions/workflows/")); - assertThat(workflowRun.getHeadBranch(), equalTo(MAIN_BRANCH)); - assertThat(workflowRun.getHeadCommit().getId(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getTreeId(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getMessage(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getTimestamp(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getAuthor().getEmail(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getCommitter().getEmail(), notNullValue()); - assertThat(workflowRun.getEvent(), equalTo(GHEvent.WORKFLOW_DISPATCH)); - assertThat(workflowRun.getStatus(), equalTo(Status.COMPLETED)); - assertThat(workflowRun.getConclusion(), equalTo(Conclusion.SUCCESS)); - assertThat(workflowRun.getHeadSha(), notNullValue()); - assertThat(workflowRun.getTriggeringActor(), hasProperty("login", equalTo("octocat"))); + List artifacts = new ArrayList<>(workflowRun.listArtifacts().toList()); + artifacts.sort((a1, a2) -> a1.getName().compareTo(a2.getName())); + + assertThat(artifacts.size(), is(2)); + + // Test properties + checkArtifactProperties(artifacts.get(0), "artifact1"); + checkArtifactProperties(artifacts.get(1), "artifact2"); + + // Test download from upload-artifact@v3 infrastructure + String artifactContent = artifacts.get(0).download((is) -> { + try (ZipInputStream zis = new ZipInputStream(is)) { + StringBuilder sb = new StringBuilder(); + + ZipEntry ze = zis.getNextEntry(); + assertThat(ze.getName(), is("artifact1.txt")); + + // the scanner has to be kept open to avoid closing zis + Scanner scanner = new Scanner(zis); + while (scanner.hasNextLine()) { + sb.append(scanner.nextLine()); + } + + return sb.toString(); + } + }); + + // Test download from upload-artifact@v4 infrastructure + artifactContent = artifacts.get(1).download((is) -> { + try (ZipInputStream zis = new ZipInputStream(is)) { + StringBuilder sb = new StringBuilder(); + + ZipEntry ze = zis.getNextEntry(); + assertThat(ze.getName(), is("artifact2.txt")); + + // the scanner has to be kept open to avoid closing zis + Scanner scanner = new Scanner(zis); + while (scanner.hasNextLine()) { + sb.append(scanner.nextLine()); + } + + return sb.toString(); + } + }); + + assertThat(artifactContent, is("artifact2")); + + // Test GHRepository#getArtifact(long) as we are sure we have artifacts around + GHArtifact artifactById = repo.getArtifact(artifacts.get(0).getId()); + checkArtifactProperties(artifactById, "artifact1"); + + artifactById = repo.getArtifact(artifacts.get(1).getId()); + checkArtifactProperties(artifactById, "artifact2"); + + // Test GHRepository#listArtifacts() as we are sure we have artifacts around + List artifactsFromRepo = new ArrayList<>( + repo.listArtifacts().withPageSize(2).iterator().nextPage()); + artifactsFromRepo.sort((a1, a2) -> a1.getName().compareTo(a2.getName())); + + // We have at least the two artifacts we just added + assertThat(artifactsFromRepo.size(), is(2)); + + // Test properties + checkArtifactProperties(artifactsFromRepo.get(0), "artifact1"); + checkArtifactProperties(artifactsFromRepo.get(1), "artifact2"); + + // Now let's test the delete() method + GHArtifact artifact1 = artifacts.get(0); + artifact1.delete(); + + try { + repo.getArtifact(artifact1.getId()); + fail("Getting the artifact should fail as it was deleted"); + } catch (GHFileNotFoundException e) { + assertThat(e.getMessage(), containsString("Not Found")); + } } /** - * Test search on branch. + * Test jobs. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testSearchOnBranch() throws IOException { - GHWorkflow workflow = repo.getWorkflow(FAST_WORKFLOW_PATH); + public void testJobs() throws IOException { + GHWorkflow workflow = repo.getWorkflow(MULTI_JOBS_WORKFLOW_PATH); long latestPreexistingWorkflowRunId = getLatestPreexistingWorkflowRunId(); - workflow.dispatch(SECOND_BRANCH); + workflow.dispatch(MAIN_BRANCH); await((nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, - FAST_WORKFLOW_NAME, - SECOND_BRANCH, + MULTI_JOBS_WORKFLOW_NAME, + MAIN_BRANCH, Status.COMPLETED, latestPreexistingWorkflowRunId).isPresent()); - GHWorkflowRun workflowRun = getWorkflowRun(FAST_WORKFLOW_NAME, - SECOND_BRANCH, - Status.COMPLETED, - latestPreexistingWorkflowRunId) - .orElseThrow(() -> new IllegalStateException("We must have a valid workflow run starting from here")); + GHWorkflowRun workflowRun = getWorkflowRun(MULTI_JOBS_WORKFLOW_NAME, + MAIN_BRANCH, + Status.COMPLETED, + latestPreexistingWorkflowRunId) + .orElseThrow(() -> new IllegalStateException("We must have a valid workflow run starting from here")); + + List jobs = workflowRun.listJobs() + .toList() + .stream() + .sorted((j1, j2) -> j1.getName().compareTo(j2.getName())) + .collect(Collectors.toList()); + + assertThat(jobs.size(), is(2)); + + GHWorkflowJob job1 = jobs.get(0); + checkJobProperties(workflowRun.getId(), job1, "job1"); + String fullLogContent = job1.downloadLogs(getLogTextInputStreamFunction()); + assertThat(fullLogContent, containsString("Hello from job1!")); + + GHWorkflowJob job2 = jobs.get(1); + checkJobProperties(workflowRun.getId(), job2, "job2"); + fullLogContent = job2.downloadLogs(getLogTextInputStreamFunction()); + assertThat(fullLogContent, containsString("Hello from job2!")); - assertThat(workflowRun.getWorkflowId(), equalTo(workflow.getId())); - assertThat(workflowRun.getHeadBranch(), equalTo(SECOND_BRANCH)); - assertThat(workflowRun.getEvent(), equalTo(GHEvent.WORKFLOW_DISPATCH)); - assertThat(workflowRun.getStatus(), equalTo(Status.COMPLETED)); - assertThat(workflowRun.getConclusion(), equalTo(Conclusion.SUCCESS)); + // while we have a job around, test GHRepository#getWorkflowJob(id) + GHWorkflowJob job1ById = repo.getWorkflowJob(job1.getId()); + checkJobProperties(workflowRun.getId(), job1ById, "job1"); + + // Also test listAllJobs() works correctly + List allJobs = workflowRun.listAllJobs().withPageSize(10).iterator().nextPage(); + assertThat(allJobs.size(), greaterThanOrEqualTo(2)); } /** - * Test search on created and head sha. + * Test approval. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testSearchOnCreatedAndHeadSha() throws IOException { - GHWorkflow workflow = repo.getWorkflow(FAST_WORKFLOW_PATH); - - long latestPreexistingWorkflowRunId = getLatestPreexistingWorkflowRunId(); - - Instant before = Instant.parse("2024-02-09T10:19:00.00Z"); + public void testApproval() throws IOException { + List pullRequests = repo.queryPullRequests() + .base(MAIN_BRANCH) + .sort(Sort.CREATED) + .direction(GHDirection.DESC) + .state(GHIssueState.OPEN) + .list() + .toList(); - String mainBranchHeadSha = repo.getBranch(MAIN_BRANCH).getSHA1(); - String secondBranchHeadSha = repo.getBranch(SECOND_BRANCH).getSHA1(); + assertThat(pullRequests.size(), greaterThanOrEqualTo(1)); + GHPullRequest pullRequest = pullRequests.get(0); - workflow.dispatch(MAIN_BRANCH); - workflow.dispatch(SECOND_BRANCH); + await("Waiting for workflow run to be pending", + (nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, + FAST_WORKFLOW_NAME, + MAIN_BRANCH, + Conclusion.ACTION_REQUIRED).isPresent()); - await((nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, - FAST_WORKFLOW_NAME, - MAIN_BRANCH, - Status.COMPLETED, - latestPreexistingWorkflowRunId).isPresent()); - await((nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, - FAST_WORKFLOW_NAME, - SECOND_BRANCH, - Status.COMPLETED, - latestPreexistingWorkflowRunId).isPresent()); + GHWorkflowRun workflowRun = getWorkflowRun(FAST_WORKFLOW_NAME, MAIN_BRANCH, Conclusion.ACTION_REQUIRED) + .orElseThrow(() -> new IllegalStateException("We must have a valid workflow run starting from here")); - List mainBranchHeadShaWorkflowRuns = repo.queryWorkflowRuns() - .headSha(mainBranchHeadSha) - .created(">=" + before.toString()) - .list() - .toList(); - List secondBranchHeadShaWorkflowRuns = repo.queryWorkflowRuns() - .headSha(secondBranchHeadSha) - .created(">=" + before.toString()) - .list() - .toList(); + workflowRun.approve(); - assertThat(mainBranchHeadShaWorkflowRuns, hasSize(greaterThanOrEqualTo(1))); - assertThat(mainBranchHeadShaWorkflowRuns, everyItem(hasProperty("headSha", equalTo(mainBranchHeadSha)))); - // Ideally, we would use everyItem() but the bridge method is in the way - for (GHWorkflowRun workflowRun : mainBranchHeadShaWorkflowRuns) { - assertThat(workflowRun.getCreatedAt(), greaterThanOrEqualTo(before)); - } + await("Waiting for workflow run to be approved", + (nonRecordingRepo) -> getWorkflowRun(nonRecordingRepo, + FAST_WORKFLOW_NAME, + pullRequest.getHead().getRef(), + Conclusion.SUCCESS).isPresent()); - assertThat(secondBranchHeadShaWorkflowRuns, hasSize(greaterThanOrEqualTo(1))); - assertThat(secondBranchHeadShaWorkflowRuns, everyItem(hasProperty("headSha", equalTo(secondBranchHeadSha)))); - // Ideally, we would use everyItem() but the bridge method is in the way - for (GHWorkflowRun workflowRun : secondBranchHeadShaWorkflowRuns) { - assertThat(workflowRun.getCreatedAt(), greaterThanOrEqualTo(before)); - } + workflowRun = repo.getWorkflowRun(workflowRun.getId()); - List mainBranchHeadShaWorkflowRunsBefore = repo.queryWorkflowRuns() - .headSha(repo.getBranch(MAIN_BRANCH).getSHA1()) - .created("<" + before) - .list() - .toList(); - // Ideally, we would use that but the bridge method is causing issues - // assertThat(mainBranchHeadShaWorkflowRunsBefore, everyItem(hasProperty("createdAt", - // lessThan(Date.from(before))))); - for (GHWorkflowRun workflowRun : mainBranchHeadShaWorkflowRunsBefore) { - assertThat(workflowRun.getCreatedAt(), lessThan(before)); - } + assertThat(workflowRun.getConclusion(), is(Conclusion.SUCCESS)); } /** @@ -731,10 +577,6 @@ public void testStartupFailureConclusion() throws IOException { assertThat(list.get(0).getConclusion(), is(Conclusion.STARTUP_FAILURE)); } - private void await(Function condition) throws IOException { - await(null, condition); - } - private void await(String alias, Function condition) throws IOException { if (!mockGitHub.isUseProxy()) { return; @@ -747,12 +589,34 @@ private void await(String alias, Function condition) thro }); } + private void await(Function condition) throws IOException { + await(null, condition); + } + private long getLatestPreexistingWorkflowRunId() { return repo.queryWorkflowRuns().list().withPageSize(1).iterator().next().getId(); } - private Optional getWorkflowRun(String workflowName, String branch, Conclusion conclusion) { - return getWorkflowRun(this.repo, workflowName, branch, conclusion); + private static Optional getWorkflowRun(GHRepository repository, + String workflowName, + String branch, + Status status, + long latestPreexistingWorkflowRunId) { + List workflowRuns = repository.queryWorkflowRuns() + .branch(branch) + .status(status) + .event(GHEvent.WORKFLOW_DISPATCH) + .list() + .withPageSize(20) + .iterator() + .nextPage(); + + for (GHWorkflowRun workflowRun : workflowRuns) { + if (workflowRun.getName().equals(workflowName) && workflowRun.getId() > latestPreexistingWorkflowRunId) { + return Optional.of(workflowRun); + } + } + return Optional.empty(); } private Optional getWorkflowRun(String workflowName, @@ -761,4 +625,131 @@ private Optional getWorkflowRun(String workflowName, long latestPreexistingWorkflowRunId) { return getWorkflowRun(this.repo, workflowName, branch, status, latestPreexistingWorkflowRunId); } + + private static Optional getWorkflowRun(GHRepository repository, + String workflowName, + String branch, + Conclusion conclusion) { + List workflowRuns = repository.queryWorkflowRuns() + .branch(branch) + .conclusion(conclusion) + .event(GHEvent.PULL_REQUEST) + .list() + .withPageSize(20) + .iterator() + .nextPage(); + + for (GHWorkflowRun workflowRun : workflowRuns) { + if (workflowRun.getName().equals(workflowName)) { + return Optional.of(workflowRun); + } + } + return Optional.empty(); + } + + private Optional getWorkflowRun(String workflowName, String branch, Conclusion conclusion) { + return getWorkflowRun(this.repo, workflowName, branch, conclusion); + } + + private static Status getWorkflowRunStatus(GHRepository repository, long workflowRunId) { + try { + return repository.getWorkflowRun(workflowRunId).getStatus(); + } catch (IOException e) { + throw new IllegalStateException("Unable to get workflow run status", e); + } + } + + @SuppressWarnings("resource") + private static InputStreamFunction getLogArchiveInputStreamFunction(String mainLogFileName, + List logsArchiveEntries) { + return (is) -> { + try (ZipInputStream zis = new ZipInputStream(is)) { + StringBuilder sb = new StringBuilder(); + + ZipEntry ze; + while ((ze = zis.getNextEntry()) != null) { + logsArchiveEntries.add(ze.getName()); + if (mainLogFileName.equals(ze.getName())) { + // the scanner has to be kept open to avoid closing zis + Scanner scanner = new Scanner(zis); + while (scanner.hasNextLine()) { + sb.append(scanner.nextLine()).append("\n"); + } + } + } + + return sb.toString(); + } + }; + } + + @SuppressWarnings("resource") + private static InputStreamFunction getLogTextInputStreamFunction() { + return (is) -> { + StringBuilder sb = new StringBuilder(); + Scanner scanner = new Scanner(is); + while (scanner.hasNextLine()) { + sb.append(scanner.nextLine()).append("\n"); + } + return sb.toString(); + }; + } + + private static void checkArtifactProperties(GHArtifact artifact, String artifactName) throws IOException { + assertThat(artifact.getId(), notNullValue()); + assertThat(artifact.getNodeId(), notNullValue()); + assertThat(artifact.getRepository().getFullName(), equalTo(REPO_NAME)); + assertThat(artifact.getName(), is(artifactName)); + assertThat(artifact.getArchiveDownloadUrl().getPath(), containsString("actions/artifacts")); + assertThat(artifact.getCreatedAt(), notNullValue()); + assertThat(artifact.getUpdatedAt(), notNullValue()); + assertThat(artifact.getExpiresAt(), notNullValue()); + assertThat(artifact.getSizeInBytes(), greaterThan(0L)); + assertThat(artifact.isExpired(), is(false)); + } + + private static void checkJobProperties(long workflowRunId, GHWorkflowJob job, String jobName) throws IOException { + assertThat(job.getId(), notNullValue()); + assertThat(job.getNodeId(), notNullValue()); + assertThat(job.getRepository().getFullName(), equalTo(REPO_NAME)); + assertThat(job.getName(), is(jobName)); + assertThat(job.getStartedAt(), notNullValue()); + assertThat(job.getCompletedAt(), notNullValue()); + assertThat(job.getHeadSha(), notNullValue()); + assertThat(job.getStatus(), is(Status.COMPLETED)); + assertThat(job.getConclusion(), is(Conclusion.SUCCESS)); + assertThat(job.getRunId(), is(workflowRunId)); + assertThat(job.getUrl().getPath(), containsString("/actions/jobs/")); + assertThat(job.getHtmlUrl().getPath(), containsString("/runs/" + job.getId())); + assertThat(job.getCheckRunUrl().getPath(), containsString("/check-runs/")); + assertThat(job.getRunnerId(), is(1)); + assertThat(job.getRunnerName(), containsString("my runner")); + assertThat(job.getRunnerGroupId(), is(2)); + assertThat(job.getRunnerGroupName(), containsString("my runner group")); + + // we only test the step we have control over, the others are added by GitHub + Optional step = job.getSteps() + .stream() + .filter(s -> RUN_A_ONE_LINE_SCRIPT_STEP_NAME.equals(s.getName())) + .findFirst(); + if (!step.isPresent()) { + fail("Unable to find " + RUN_A_ONE_LINE_SCRIPT_STEP_NAME + " step"); + } + + Optional labelOptional = job.getLabels().stream().filter(s -> s.equals(UBUNTU_LABEL)).findFirst(); + if (!labelOptional.isPresent()) { + fail("Unable to find " + UBUNTU_LABEL + " label"); + } + + checkStepProperties(step.get(), RUN_A_ONE_LINE_SCRIPT_STEP_NAME, 2); + } + + private static void checkStepProperties(Step step, String name, int number) { + assertThat(step.getName(), is(name)); + assertThat(step.getNumber(), is(number)); + assertThat(step.getStatus(), is(Status.COMPLETED)); + assertThat(step.getConclusion(), is(Conclusion.SUCCESS)); + assertThat(step.getStartedAt(), notNullValue()); + assertThat(step.getCompletedAt(), notNullValue()); + } } diff --git a/src/test/java/org/kohsuke/github/GHWorkflowTest.java b/src/test/java/org/kohsuke/github/GHWorkflowTest.java index 836907ae91..33e3682bbd 100644 --- a/src/test/java/org/kohsuke/github/GHWorkflowTest.java +++ b/src/test/java/org/kohsuke/github/GHWorkflowTest.java @@ -21,43 +21,16 @@ */ public class GHWorkflowTest extends AbstractGitHubWireMockTest { - private static String REPO_NAME = "hub4j-test-org/GHWorkflowTest"; - - private static void checkWorkflowRunProperties(GHWorkflowRun workflowRun, long workflowId) { - assertThat(workflowRun.getWorkflowId(), equalTo(workflowId)); - assertThat(workflowRun.getId(), notNullValue()); - assertThat(workflowRun.getNodeId(), notNullValue()); - assertThat(workflowRun.getRepository().getFullName(), equalTo(REPO_NAME)); - assertThat(workflowRun.getUrl().getPath(), containsString("/actions/runs/")); - assertThat(workflowRun.getHtmlUrl().getPath(), containsString("/actions/runs/")); - assertThat(workflowRun.getJobsUrl().getPath(), endsWith("/jobs")); - assertThat(workflowRun.getLogsUrl().getPath(), endsWith("/logs")); - assertThat(workflowRun.getCheckSuiteUrl().getPath(), containsString("/check-suites/")); - assertThat(workflowRun.getArtifactsUrl().getPath(), endsWith("/artifacts")); - assertThat(workflowRun.getCancelUrl().getPath(), endsWith("/cancel")); - assertThat(workflowRun.getRerunUrl().getPath(), endsWith("/rerun")); - assertThat(workflowRun.getWorkflowUrl().getPath(), containsString("/actions/workflows/")); - assertThat(workflowRun.getHeadBranch(), equalTo("main")); - assertThat(workflowRun.getHeadCommit().getId(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getTreeId(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getMessage(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getTimestamp(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getAuthor().getEmail(), notNullValue()); - assertThat(workflowRun.getHeadCommit().getCommitter().getEmail(), notNullValue()); - assertThat(workflowRun.getEvent(), equalTo(GHEvent.WORKFLOW_DISPATCH)); - assertThat(workflowRun.getStatus(), equalTo(GHWorkflowRun.Status.COMPLETED)); - assertThat(workflowRun.getConclusion(), equalTo(GHWorkflowRun.Conclusion.SUCCESS)); - assertThat(workflowRun.getHeadSha(), notNullValue()); - } - - private GHRepository repo; - /** * Create default GHWorkflowTest instance */ public GHWorkflowTest() { } + private static String REPO_NAME = "hub4j-test-org/GHWorkflowTest"; + + private GHRepository repo; + /** * Cleanup. * @@ -159,23 +132,6 @@ public void testDispatch() throws IOException { .withRequestBody(containing("value"))); } - /** - * Test list workflow runs. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testListWorkflowRuns() throws IOException { - GHWorkflow workflow = repo.getWorkflow("test-workflow.yml"); - - List workflowRuns = workflow.listRuns().toList(); - assertThat(workflowRuns.size(), greaterThan(2)); - - checkWorkflowRunProperties(workflowRuns.get(0), workflow.getId()); - checkWorkflowRunProperties(workflowRuns.get(1), workflow.getId()); - } - /** * Test list workflows. * @@ -200,4 +156,48 @@ public void testListWorkflows() throws IOException { equalTo("/hub4j-test-org/GHWorkflowTest/workflows/test-workflow/badge.svg")); } + /** + * Test list workflow runs. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testListWorkflowRuns() throws IOException { + GHWorkflow workflow = repo.getWorkflow("test-workflow.yml"); + + List workflowRuns = workflow.listRuns().toList(); + assertThat(workflowRuns.size(), greaterThan(2)); + + checkWorkflowRunProperties(workflowRuns.get(0), workflow.getId()); + checkWorkflowRunProperties(workflowRuns.get(1), workflow.getId()); + } + + private static void checkWorkflowRunProperties(GHWorkflowRun workflowRun, long workflowId) throws IOException { + assertThat(workflowRun.getWorkflowId(), equalTo(workflowId)); + assertThat(workflowRun.getId(), notNullValue()); + assertThat(workflowRun.getNodeId(), notNullValue()); + assertThat(workflowRun.getRepository().getFullName(), equalTo(REPO_NAME)); + assertThat(workflowRun.getUrl().getPath(), containsString("/actions/runs/")); + assertThat(workflowRun.getHtmlUrl().getPath(), containsString("/actions/runs/")); + assertThat(workflowRun.getJobsUrl().getPath(), endsWith("/jobs")); + assertThat(workflowRun.getLogsUrl().getPath(), endsWith("/logs")); + assertThat(workflowRun.getCheckSuiteUrl().getPath(), containsString("/check-suites/")); + assertThat(workflowRun.getArtifactsUrl().getPath(), endsWith("/artifacts")); + assertThat(workflowRun.getCancelUrl().getPath(), endsWith("/cancel")); + assertThat(workflowRun.getRerunUrl().getPath(), endsWith("/rerun")); + assertThat(workflowRun.getWorkflowUrl().getPath(), containsString("/actions/workflows/")); + assertThat(workflowRun.getHeadBranch(), equalTo("main")); + assertThat(workflowRun.getHeadCommit().getId(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getTreeId(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getMessage(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getTimestamp(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getAuthor().getEmail(), notNullValue()); + assertThat(workflowRun.getHeadCommit().getCommitter().getEmail(), notNullValue()); + assertThat(workflowRun.getEvent(), equalTo(GHEvent.WORKFLOW_DISPATCH)); + assertThat(workflowRun.getStatus(), equalTo(GHWorkflowRun.Status.COMPLETED)); + assertThat(workflowRun.getConclusion(), equalTo(GHWorkflowRun.Conclusion.SUCCESS)); + assertThat(workflowRun.getHeadSha(), notNullValue()); + } + } diff --git a/src/test/java/org/kohsuke/github/GitHubConnectionTest.java b/src/test/java/org/kohsuke/github/GitHubConnectionTest.java index 148e06ec49..bb863eae72 100644 --- a/src/test/java/org/kohsuke/github/GitHubConnectionTest.java +++ b/src/test/java/org/kohsuke/github/GitHubConnectionTest.java @@ -32,23 +32,112 @@ public GitHubConnectionTest() { } /** - * Test anonymous. + * Test offline. + * + * @throws Exception + * the exception + */ + @Test + public void testOffline() throws Exception { + GitHub hub = GitHub.offline(); + assertThat(GitHubRequest.getApiURL(hub.getClient().getApiUrl(), "/test").toString(), + equalTo("https://api.github.invalid/test")); + assertThat(hub.isAnonymous(), is(true)); + try { + hub.getRateLimit(); + fail("Offline instance should always fail"); + } catch (IOException e) { + assertThat(e.getMessage(), equalTo("Offline")); + } + } + + /** + * Test git hub server with http. + * + * @throws Exception + * the exception + */ + @Test + public void testGitHubServerWithHttp() throws Exception { + GitHub hub = GitHub.connectToEnterpriseWithOAuth("http://enterprise.kohsuke.org/api/v3", "bogus", "bogus"); + assertThat(GitHubRequest.getApiURL(hub.getClient().getApiUrl(), "/test").toString(), + equalTo("http://enterprise.kohsuke.org/api/v3/test")); + } + + /** + * Test git hub server with https. + * + * @throws Exception + * the exception + */ + @Test + public void testGitHubServerWithHttps() throws Exception { + GitHub hub = GitHub.connectToEnterpriseWithOAuth("https://enterprise.kohsuke.org/api/v3", "bogus", "bogus"); + assertThat(GitHubRequest.getApiURL(hub.getClient().getApiUrl(), "/test").toString(), + equalTo("https://enterprise.kohsuke.org/api/v3/test")); + } + + /** + * Test git hub server without server. + * + * @throws Exception + * the exception + */ + @Test + public void testGitHubServerWithoutServer() throws Exception { + GitHub hub = GitHub.connect("kohsuke", "bogus"); + assertThat(GitHubRequest.getApiURL(hub.getClient().getApiUrl(), "/test").toString(), + equalTo("https://api.github.com/test")); + } + + /** + * Test git hub builder from environment. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testAnonymous() { + public void testGitHubBuilderFromEnvironment() throws IOException { // we disable this test for JDK 16+ as the current hacks in setupEnvironment() don't work with JDK 16+ Assume.assumeThat(Double.valueOf(System.getProperty("java.specification.version")), lessThan(16.0)); Map props = new HashMap(); - props.put("endpoint", mockGitHub.apiServer().baseUrl()); + props.put("endpoint", "bogus endpoint url"); + props.put("oauth", "bogus oauth token string"); setupEnvironment(props); - - // No values present except endpoint GitHubBuilder builder = GitHubBuilder.fromEnvironment(); - assertThat(builder.endpoint, equalTo(mockGitHub.apiServer().baseUrl())); - assertThat(builder.authorizationProvider, sameInstance(AuthorizationProvider.ANONYMOUS)); + assertThat(builder.endpoint, equalTo("bogus endpoint url")); + + assertThat(builder.authorizationProvider, instanceOf(UserAuthorizationProvider.class)); + assertThat(builder.authorizationProvider.getEncodedAuthorization(), equalTo("token bogus oauth token string")); + assertThat(((UserAuthorizationProvider) builder.authorizationProvider).getLogin(), nullValue()); + + props.put("login", "bogus login"); + setupEnvironment(props); + builder = GitHubBuilder.fromEnvironment(); + + assertThat(builder.authorizationProvider, instanceOf(UserAuthorizationProvider.class)); + assertThat(builder.authorizationProvider.getEncodedAuthorization(), equalTo("token bogus oauth token string")); + assertThat(((UserAuthorizationProvider) builder.authorizationProvider).getLogin(), equalTo("bogus login")); + + props.put("jwt", "bogus jwt token string"); + setupEnvironment(props); + builder = GitHubBuilder.fromEnvironment(); + + assertThat(builder.authorizationProvider, not(instanceOf(UserAuthorizationProvider.class))); + assertThat(builder.authorizationProvider.getEncodedAuthorization(), equalTo("Bearer bogus jwt token string")); + + // props.put("password", "bogus weak password"); + // setupEnvironment(props); + // builder = GitHubBuilder.fromEnvironment(); + + // assertThat(builder.authorizationProvider, instanceOf(UserAuthorizationProvider.class)); + // assertThat(builder.authorizationProvider.getEncodedAuthorization(), + // equalTo("Basic Ym9ndXMgbG9naW46Ym9ndXMgd2VhayBwYXNzd29yZA==")); + // assertThat(((UserAuthorizationProvider) builder.authorizationProvider).getLogin(), equalTo("bogus login")); + } /** @@ -157,54 +246,59 @@ public void testGitHubBuilderFromCredentialsWithPropertyFile() throws IOExceptio } } + private void setupPropertyFile(Map props) throws IOException { + File propertyFile = new File(getTestDirectory(), ".github"); + Properties properties = new Properties(); + properties.putAll(props); + properties.store(new FileOutputStream(propertyFile), ""); + } + + private String getTestDirectory() { + return new File("target").getAbsolutePath(); + } + /** - * Test git hub builder from environment. + * Test anonymous. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void testGitHubBuilderFromEnvironment() throws IOException { + public void testAnonymous() throws IOException { // we disable this test for JDK 16+ as the current hacks in setupEnvironment() don't work with JDK 16+ Assume.assumeThat(Double.valueOf(System.getProperty("java.specification.version")), lessThan(16.0)); Map props = new HashMap(); - props.put("endpoint", "bogus endpoint url"); - props.put("oauth", "bogus oauth token string"); - setupEnvironment(props); - GitHubBuilder builder = GitHubBuilder.fromEnvironment(); - - assertThat(builder.endpoint, equalTo("bogus endpoint url")); - - assertThat(builder.authorizationProvider, instanceOf(UserAuthorizationProvider.class)); - assertThat(builder.authorizationProvider.getEncodedAuthorization(), equalTo("token bogus oauth token string")); - assertThat(((UserAuthorizationProvider) builder.authorizationProvider).getLogin(), nullValue()); - - props.put("login", "bogus login"); + props.put("endpoint", mockGitHub.apiServer().baseUrl()); setupEnvironment(props); - builder = GitHubBuilder.fromEnvironment(); - - assertThat(builder.authorizationProvider, instanceOf(UserAuthorizationProvider.class)); - assertThat(builder.authorizationProvider.getEncodedAuthorization(), equalTo("token bogus oauth token string")); - assertThat(((UserAuthorizationProvider) builder.authorizationProvider).getLogin(), equalTo("bogus login")); - props.put("jwt", "bogus jwt token string"); - setupEnvironment(props); - builder = GitHubBuilder.fromEnvironment(); + // No values present except endpoint + GitHubBuilder builder = GitHubBuilder.fromEnvironment(); - assertThat(builder.authorizationProvider, not(instanceOf(UserAuthorizationProvider.class))); - assertThat(builder.authorizationProvider.getEncodedAuthorization(), equalTo("Bearer bogus jwt token string")); + assertThat(builder.endpoint, equalTo(mockGitHub.apiServer().baseUrl())); + assertThat(builder.authorizationProvider, sameInstance(AuthorizationProvider.ANONYMOUS)); + } - // props.put("password", "bogus weak password"); - // setupEnvironment(props); - // builder = GitHubBuilder.fromEnvironment(); + /** + * Test github builder with app installation token. + * + * @throws Exception + * the exception + */ + @Test + public void testGithubBuilderWithAppInstallationToken() throws Exception { + GitHubBuilder builder = new GitHubBuilder().withAppInstallationToken("bogus app token"); // assertThat(builder.authorizationProvider, instanceOf(UserAuthorizationProvider.class)); - // assertThat(builder.authorizationProvider.getEncodedAuthorization(), - // equalTo("Basic Ym9ndXMgbG9naW46Ym9ndXMgd2VhayBwYXNzd29yZA==")); - // assertThat(((UserAuthorizationProvider) builder.authorizationProvider).getLogin(), equalTo("bogus login")); + assertThat(builder.authorizationProvider.getEncodedAuthorization(), equalTo("token bogus app token")); + assertThat(((UserAuthorizationProvider) builder.authorizationProvider).getLogin(), is(emptyString())); + // test authorization header is set as in the RFC6749 + GitHub github = builder.build(); + // change this to get a request + assertThat(github.getClient().getEncodedAuthorization(), equalTo("token bogus app token")); + assertThat(github.getClient().getLogin(), is(emptyString())); } /** @@ -261,87 +355,6 @@ public void testGitHubOAuthUserQuery() throws IOException { assertThat(mockGitHub.getRequestCount(), equalTo(1)); } - /** - * Test git hub server with http. - * - * @throws Exception - * the exception - */ - @Test - public void testGitHubServerWithHttp() throws Exception { - GitHub hub = GitHub.connectToEnterpriseWithOAuth("http://enterprise.kohsuke.org/api/v3", "bogus", "bogus"); - assertThat(GitHubRequest.getApiURL(hub.getClient().getApiUrl(), "/test").toString(), - equalTo("http://enterprise.kohsuke.org/api/v3/test")); - } - - /** - * Test git hub server with https. - * - * @throws Exception - * the exception - */ - @Test - public void testGitHubServerWithHttps() throws Exception { - GitHub hub = GitHub.connectToEnterpriseWithOAuth("https://enterprise.kohsuke.org/api/v3", "bogus", "bogus"); - assertThat(GitHubRequest.getApiURL(hub.getClient().getApiUrl(), "/test").toString(), - equalTo("https://enterprise.kohsuke.org/api/v3/test")); - } - - /** - * Test git hub server without server. - * - * @throws Exception - * the exception - */ - @Test - public void testGitHubServerWithoutServer() throws Exception { - GitHub hub = GitHub.connect("kohsuke", "bogus"); - assertThat(GitHubRequest.getApiURL(hub.getClient().getApiUrl(), "/test").toString(), - equalTo("https://api.github.com/test")); - } - - /** - * Test github builder with app installation token. - * - * @throws Exception - * the exception - */ - @Test - public void testGithubBuilderWithAppInstallationToken() throws Exception { - - GitHubBuilder builder = new GitHubBuilder().withAppInstallationToken("bogus app token"); - // assertThat(builder.authorizationProvider, instanceOf(UserAuthorizationProvider.class)); - assertThat(builder.authorizationProvider.getEncodedAuthorization(), equalTo("token bogus app token")); - assertThat(((UserAuthorizationProvider) builder.authorizationProvider).getLogin(), is(emptyString())); - - // test authorization header is set as in the RFC6749 - GitHub github = builder.build(); - // change this to get a request - assertThat(github.getClient().getEncodedAuthorization(), equalTo("token bogus app token")); - assertThat(github.getClient().getLogin(), is(emptyString())); - } - - /** - * Test offline. - */ - @Test - public void testOffline() { - GitHub hub = GitHub.offline(); - assertThat(GitHubRequest.getApiURL(hub.getClient().getApiUrl(), "/test").toString(), - equalTo("https://api.github.invalid/test")); - assertThat(hub.isAnonymous(), is(true)); - try { - hub.getRateLimit(); - fail("Offline instance should always fail"); - } catch (IOException e) { - assertThat(e.getMessage(), equalTo("Offline")); - } - } - - private String getTestDirectory() { - return new File("target").getAbsolutePath(); - } - /* * Copied from StackOverflow: http://stackoverflow.com/a/7201825/2336755 * @@ -383,11 +396,4 @@ private void setupEnvironment(Map newenv) { e1.printStackTrace(); } } - - private void setupPropertyFile(Map props) throws IOException { - File propertyFile = new File(getTestDirectory(), ".github"); - Properties properties = new Properties(); - properties.putAll(props); - properties.store(new FileOutputStream(propertyFile), ""); - } } diff --git a/src/test/java/org/kohsuke/github/GitHubStaticTest.java b/src/test/java/org/kohsuke/github/GitHubStaticTest.java index 5db7bc1ead..729b130a8c 100644 --- a/src/test/java/org/kohsuke/github/GitHubStaticTest.java +++ b/src/test/java/org/kohsuke/github/GitHubStaticTest.java @@ -6,20 +6,20 @@ import java.net.MalformedURLException; import java.net.URL; +import java.text.SimpleDateFormat; import java.time.Duration; import java.time.Instant; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoUnit; import java.util.Date; -import java.util.Locale; +import java.util.TimeZone; import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.fail; // TODO: Auto-generated Javadoc /** @@ -30,45 +30,130 @@ public class GitHubStaticTest extends AbstractGitHubWireMockTest { /** - * Format instant. + * Create default GitHubStaticTest instance + */ + public GitHubStaticTest() { + } + + /** + * Test parse URL. * - * @param instant - * the instant - * @param format - * the format - * @return the string + * @throws Exception + * the exception */ - static String formatInstant(Instant instant, String format) { - return formatZonedInstant(instant, format, "GMT"); + @Test + public void testParseURL() throws Exception { + assertThat(GitHubClient.parseURL("https://api.github.com"), equalTo(new URL("https://api.github.com"))); + assertThat(GitHubClient.parseURL(null), nullValue()); + + try { + GitHubClient.parseURL("bogus"); + fail(); + } catch (IllegalStateException e) { + assertThat(e.getMessage(), equalTo("Invalid URL: bogus")); + } } /** - * Format zoned instant. + * Test parse instant. * - * @param instant - * the instant - * @param format - * the format - * @param timeZone - * the time zone - * @return the string + * @throws Exception + * the exception */ - static String formatZonedInstant(Instant instant, String format, String timeZone) { - return DateTimeFormatter.ofPattern(format, Locale.ENGLISH) - .format(instant.atZone(ZoneId.of(timeZone, ZoneId.SHORT_IDS))); + @Test + public void testParseInstant() throws Exception { + assertThat(GitHubClient.parseInstant(null), nullValue()); } /** - * Create default GitHubStaticTest instance + * Test raw url path invalid. + * + * @throws Exception + * the exception */ - public GitHubStaticTest() { + @Test + public void testRawUrlPathInvalid() throws Exception { + try { + gitHub.createRequest().setRawUrlPath("invalid.path.com"); + fail(); + } catch (GHException e) { + assertThat(e.getMessage(), equalTo("Raw URL must start with 'http'")); + } + } + + /** + * Time round trip. + * + * @throws Exception + * the exception + */ + @Test + public void timeRoundTrip() throws Exception { + final long stableInstantEpochMilli = 1533721222255L; + Instant instantNow = Instant.ofEpochMilli(stableInstantEpochMilli); + + Date instantSeconds = Date.from(instantNow.truncatedTo(ChronoUnit.SECONDS)); + Date instantMillis = Date.from(instantNow.truncatedTo(ChronoUnit.MILLIS)); + + String instantFormatSlash = formatZonedDate(instantMillis, "yyyy/MM/dd HH:mm:ss ZZZZ", "PST"); + assertThat(instantFormatSlash, equalTo("2018/08/08 02:40:22 -0700")); + + String instantFormatDash = formatDate(instantMillis, "yyyy-MM-dd'T'HH:mm:ss'Z'"); + assertThat(instantFormatDash, equalTo("2018-08-08T09:40:22Z")); + + String instantFormatMillis = formatDate(instantMillis, "yyyy-MM-dd'T'HH:mm:ss.S'Z'"); + assertThat(instantFormatMillis, equalTo("2018-08-08T09:40:22.255Z")); + + String instantFormatMillisZoned = formatZonedDate(instantMillis, "yyyy-MM-dd'T'HH:mm:ss.SXXX", "PST"); + assertThat(instantFormatMillisZoned, equalTo("2018-08-08T02:40:22.255-07:00")); + + String instantSecondsFormatMillis = formatDate(instantSeconds, "yyyy-MM-dd'T'HH:mm:ss.S'Z'"); + assertThat(instantSecondsFormatMillis, equalTo("2018-08-08T09:40:22.0Z")); + + String instantSecondsFormatMillisZoned = formatZonedDate(instantSeconds, "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", "PST"); + assertThat(instantSecondsFormatMillisZoned, equalTo("2018-08-08T02:40:22.000-07:00")); + + String instantBadFormat = formatDate(instantMillis, "yy-MM-dd'T'HH:mm'Z'"); + assertThat(instantBadFormat, equalTo("18-08-08T09:40Z")); + + assertThat(GitHubClient.parseDate(GitHubClient.printDate(instantSeconds)), + equalTo(GitHubClient.parseDate(GitHubClient.printDate(instantMillis)))); + assertThat(GitHubClient.printDate(instantSeconds), equalTo("2018-08-08T09:40:22Z")); + assertThat(GitHubClient.printDate(GitHubClient.parseDate(instantFormatMillisZoned)), + equalTo("2018-08-08T09:40:22Z")); + + assertThat(instantSeconds, equalTo(GitHubClient.parseDate(GitHubClient.printDate(instantSeconds)))); + + // printDate will truncate to the nearest second, so it should not be equal + assertThat(instantMillis, not(equalTo(GitHubClient.parseDate(GitHubClient.printDate(instantMillis))))); + + assertThat(instantSeconds, equalTo(GitHubClient.parseDate(instantFormatSlash))); + + assertThat(instantSeconds, equalTo(GitHubClient.parseDate(instantFormatDash))); + + // This parser does not truncate to the nearest second, so it will be equal + assertThat(instantMillis, equalTo(GitHubClient.parseDate(instantFormatMillis))); + assertThat(instantMillis, equalTo(GitHubClient.parseDate(instantFormatMillisZoned))); + + assertThat(instantSeconds, equalTo(GitHubClient.parseDate(instantSecondsFormatMillis))); + assertThat(instantSeconds, equalTo(GitHubClient.parseDate(instantSecondsFormatMillisZoned))); + + try { + GitHubClient.parseDate(instantBadFormat); + fail("Bad time format should throw."); + } catch (DateTimeParseException e) { + assertThat(e.getMessage(), equalTo("Text '" + instantBadFormat + "' could not be parsed at index 0")); + } } /** * Test from record. + * + * @throws Exception + * the exception */ @Test - public void testFromRecord() { + public void testFromRecord() throws Exception { final long stableInstantEpochSeconds = 11610674762L; GHRateLimit rateLimit_none = GHRateLimit.fromRecord(new GHRateLimit.Record(9876, @@ -266,41 +351,6 @@ public void testGitHubRateLimitShouldReplaceRateLimit() throws Exception { } - /** - * Test git hub request get api URL. - */ - @Test - public void testGitHubRequest_getApiURL() { - assertThat(GitHubRequest.getApiURL("github.com", "/endpoint").toString(), - equalTo("https://api.github.com/endpoint")); - - // This URL is completely invalid but doesn't throw - assertThat(GitHubRequest.getApiURL("github.com", "//endpoint&?").toString(), - equalTo("https://api.github.com//endpoint&?")); - - assertThat(GitHubRequest.getApiURL("ftp://whoa.github.com", "/endpoint").toString(), - equalTo("ftp://whoa.github.com/endpoint")); - assertThat(GitHubRequest.getApiURL(null, "ftp://api.test.github.com/endpoint").toString(), - equalTo("ftp://api.test.github.com/endpoint")); - - GHException e; - e = Assert.assertThrows(GHException.class, - () -> GitHubRequest.getApiURL("gopher://whoa.github.com", "/endpoint")); - assertThat(e.getMessage(), equalTo("Unable to build GitHub API URL")); - assertThat(e.getCause(), instanceOf(MalformedURLException.class)); - assertThat(e.getCause().getMessage(), equalTo("unknown protocol: gopher")); - - e = Assert.assertThrows(GHException.class, () -> GitHubRequest.getApiURL("bogus", "/endpoint")); - assertThat(e.getCause(), instanceOf(IllegalArgumentException.class)); - assertThat(e.getCause().getMessage(), equalTo("URI is not absolute")); - - e = Assert.assertThrows(GHException.class, - () -> GitHubRequest.getApiURL(null, "gopher://api.test.github.com/endpoint")); - assertThat(e.getCause(), instanceOf(MalformedURLException.class)); - assertThat(e.getCause().getMessage(), equalTo("unknown protocol: gopher")); - - } - /** * Test mapping reader writer. * @@ -345,113 +395,71 @@ public void testMappingReaderWriter() throws Exception { } /** - * Test parse instant. - */ - @Test - public void testParseInstant() { - assertThat(GitHubClient.parseInstant(null), nullValue()); - } - - /** - * Test parse URL. + * Test git hub request get api URL. * * @throws Exception * the exception */ @Test - public void testParseURL() throws Exception { - assertThat(GitHubClient.parseURL("https://api.github.com"), equalTo(new URL("https://api.github.com"))); - assertThat(GitHubClient.parseURL(null), nullValue()); + public void testGitHubRequest_getApiURL() throws Exception { + assertThat(GitHubRequest.getApiURL("github.com", "/endpoint").toString(), + equalTo("https://api.github.com/endpoint")); + + // This URL is completely invalid but doesn't throw + assertThat(GitHubRequest.getApiURL("github.com", "//endpoint&?").toString(), + equalTo("https://api.github.com//endpoint&?")); + + assertThat(GitHubRequest.getApiURL("ftp://whoa.github.com", "/endpoint").toString(), + equalTo("ftp://whoa.github.com/endpoint")); + assertThat(GitHubRequest.getApiURL(null, "ftp://api.test.github.com/endpoint").toString(), + equalTo("ftp://api.test.github.com/endpoint")); + + GHException e; + e = Assert.assertThrows(GHException.class, + () -> GitHubRequest.getApiURL("gopher://whoa.github.com", "/endpoint")); + assertThat(e.getMessage(), equalTo("Unable to build GitHub API URL")); + assertThat(e.getCause(), instanceOf(MalformedURLException.class)); + assertThat(e.getCause().getMessage(), equalTo("unknown protocol: gopher")); + + e = Assert.assertThrows(GHException.class, () -> GitHubRequest.getApiURL("bogus", "/endpoint")); + assertThat(e.getCause(), instanceOf(IllegalArgumentException.class)); + assertThat(e.getCause().getMessage(), equalTo("URI is not absolute")); + + e = Assert.assertThrows(GHException.class, + () -> GitHubRequest.getApiURL(null, "gopher://api.test.github.com/endpoint")); + assertThat(e.getCause(), instanceOf(MalformedURLException.class)); + assertThat(e.getCause().getMessage(), equalTo("unknown protocol: gopher")); - try { - GitHubClient.parseURL("bogus"); - fail(); - } catch (IllegalStateException e) { - assertThat(e.getMessage(), equalTo("Invalid URL: bogus")); - } } /** - * Test raw url path invalid. + * Format date. + * + * @param dt + * the dt + * @param format + * the format + * @return the string */ - @Test - public void testRawUrlPathInvalid() { - try { - gitHub.createRequest().setRawUrlPath("invalid.path.com"); - fail(); - } catch (GHException e) { - assertThat(e.getMessage(), equalTo("Raw URL must start with 'http'")); - } + static String formatDate(Date dt, String format) { + return formatZonedDate(dt, format, "GMT"); } /** - * Time round trip. + * Format zoned date. + * + * @param dt + * the dt + * @param format + * the format + * @param timeZone + * the time zone + * @return the string */ - @Test - public void timeRoundTrip() { - final long stableInstantEpochMilli = 1533721222255L; - Instant instantNow = Instant.ofEpochMilli(stableInstantEpochMilli); - - Instant instantSeconds = instantNow.truncatedTo(ChronoUnit.SECONDS); - Instant instantMillis = instantNow.truncatedTo(ChronoUnit.MILLIS); - - String instantFormatSlash = formatZonedInstant(instantMillis, "yyyy/MM/dd HH:mm:ss Z", "PST"); - assertThat(instantFormatSlash, equalTo("2018/08/08 02:40:22 -0700")); - - String instantFormatDash = formatInstant(instantMillis, "yyyy-MM-dd'T'HH:mm:ss'Z'"); - assertThat(instantFormatDash, equalTo("2018-08-08T09:40:22Z")); - - String instantFormatMillis = formatInstant(instantMillis, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); - assertThat(instantFormatMillis, equalTo("2018-08-08T09:40:22.255Z")); - - String instantFormatMillisZoned = formatZonedInstant(instantMillis, "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", "PST"); - assertThat(instantFormatMillisZoned, equalTo("2018-08-08T02:40:22.255-07:00")); - - String instantSecondsFormatMillis = formatInstant(instantSeconds, "yyyy-MM-dd'T'HH:mm:ss.S'Z'"); - assertThat(instantSecondsFormatMillis, equalTo("2018-08-08T09:40:22.0Z")); - - String instantSecondsFormatMillisZoned = formatZonedInstant(instantSeconds, - "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", - "PST"); - assertThat(instantSecondsFormatMillisZoned, equalTo("2018-08-08T02:40:22.000-07:00")); - - String instantBadFormat = formatInstant(instantMillis, "yy-MM-dd'T'HH:mm'Z'"); - assertThat(instantBadFormat, equalTo("18-08-08T09:40Z")); - - assertThat(GitHubClient.parseInstant(GitHubClient.printInstant(instantSeconds)), - equalTo(GitHubClient.parseInstant(GitHubClient.printInstant(instantMillis)))); - assertThat(GitHubClient.printInstant(instantSeconds), equalTo("2018-08-08T09:40:22Z")); - assertThat(GitHubClient.printInstant(GitHubClient.parseInstant(instantFormatMillisZoned)), - equalTo("2018-08-08T09:40:22Z")); - - assertThat(instantSeconds, equalTo(GitHubClient.parseInstant(GitHubClient.printInstant(instantSeconds)))); - - // printDate will truncate to the nearest second, so it should not be equal - assertThat(instantMillis, not(equalTo(GitHubClient.parseInstant(GitHubClient.printInstant(instantMillis))))); - - assertThat(instantSeconds, equalTo(GitHubClient.parseInstant(instantFormatSlash))); - - assertThat(instantSeconds, equalTo(GitHubClient.parseInstant(instantFormatDash))); - - // This parser does not truncate to the nearest second, so it will be equal - assertThat(instantMillis, equalTo(GitHubClient.parseInstant(instantFormatMillis))); - assertThat(instantMillis, equalTo(GitHubClient.parseInstant(instantFormatMillisZoned))); - - assertThat(instantSeconds, equalTo(GitHubClient.parseInstant(instantSecondsFormatMillis))); - assertThat(instantSeconds, equalTo(GitHubClient.parseInstant(instantSecondsFormatMillisZoned))); - - try { - GitHubClient.parseInstant(instantBadFormat); - fail("Bad time format should throw."); - } catch (DateTimeParseException e) { - assertThat(e.getMessage(), equalTo("Text '" + instantBadFormat + "' could not be parsed at index 0")); - } - - final GitHubBridgeAdapterObject bridge = new GitHubBridgeAdapterObject() { - }; - assertThat(bridge.instantToDate(null, null), nullValue()); - assertThat(bridge.instantToDate(Instant.ofEpochMilli(stableInstantEpochMilli), null), - equalTo(Date.from(instantNow))); + static String formatZonedDate(Date dt, String format, String timeZone) { + SimpleDateFormat df = new SimpleDateFormat(format); + df.setTimeZone(TimeZone.getTimeZone(timeZone)); + return df.format(dt); } } diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 794eff5297..ada391e326 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -24,98 +24,46 @@ public GitHubTest() { } /** - * Gets the meta. + * List users. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void getMeta() throws IOException { - GHMeta meta = gitHub.getMeta(); - assertThat(meta.isVerifiablePasswordAuthentication(), is(true)); - assertThat(meta.getSshKeyFingerprints().size(), equalTo(4)); - assertThat(meta.getSshKeys().size(), equalTo(3)); - assertThat(meta.getApi().size(), equalTo(19)); - assertThat(meta.getGit().size(), equalTo(36)); - assertThat(meta.getHooks().size(), equalTo(4)); - assertThat(meta.getImporter().size(), equalTo(3)); - assertThat(meta.getPages().size(), equalTo(6)); - assertThat(meta.getWeb().size(), equalTo(20)); - assertThat(meta.getPackages().size(), equalTo(25)); - assertThat(meta.getActions().size(), equalTo(1739)); - assertThat(meta.getDependabot().size(), equalTo(3)); - - // Also test examples here - Class[] examples = new Class[]{ ReadOnlyObjects.GHMetaPublic.class, ReadOnlyObjects.GHMetaPackage.class, - ReadOnlyObjects.GHMetaGettersUnmodifiable.class, ReadOnlyObjects.GHMetaGettersFinal.class, - ReadOnlyObjects.GHMetaGettersFinalCreator.class, }; - - for (Class metaClass : examples) { - ReadOnlyObjects.GHMetaExample metaExample = gitHub.createRequest() - .withUrlPath("/meta") - .fetch((Class) metaClass); - assertThat(metaExample.isVerifiablePasswordAuthentication(), is(true)); - assertThat(metaExample.getApi().size(), equalTo(19)); - assertThat(metaExample.getGit().size(), equalTo(36)); - assertThat(metaExample.getHooks().size(), equalTo(4)); - assertThat(metaExample.getImporter().size(), equalTo(3)); - assertThat(metaExample.getPages().size(), equalTo(6)); - assertThat(metaExample.getWeb().size(), equalTo(20)); + public void listUsers() throws IOException { + for (GHUser u : Iterables.limit(gitHub.listUsers(), 10)) { + assert u.getName() != null; + // System.out.println(u.getName()); } } /** - * Gets the my marketplace purchases. + * Gets the repository. * * @throws IOException * Signals that an I/O exception has occurred. */ @Test - public void getMyMarketplacePurchases() throws IOException { - List userPurchases = gitHub.getMyMarketplacePurchases().toList(); - assertThat(userPurchases.size(), equalTo(2)); - - for (GHMarketplaceUserPurchase userPurchase : userPurchases) { - assertThat(userPurchase.isOnFreeTrial(), is(false)); - assertThat(userPurchase.getFreeTrialEndsOn(), nullValue()); - assertThat(userPurchase.getBillingCycle(), equalTo("monthly")); - assertThat(userPurchase.getNextBillingDate(), - equalTo(GitHubClient.parseInstant("2020-01-01T00:00:00.000+13:00"))); - assertThat(userPurchase.getUpdatedAt(), - equalTo(GitHubClient.parseInstant("2019-12-02T00:00:00.000+13:00"))); - - GHMarketplacePlan plan = userPurchase.getPlan(); - // GHMarketplacePlan - Non-nullable fields - assertThat(plan.getUrl(), notNullValue()); - assertThat(plan.getAccountsUrl(), notNullValue()); - assertThat(plan.getName(), notNullValue()); - assertThat(plan.getDescription(), notNullValue()); - assertThat(plan.getPriceModel(), notNullValue()); - assertThat(plan.getState(), notNullValue()); - - // GHMarketplacePlan - primitive fields - assertThat(plan.getId(), not(0L)); - assertThat(plan.getNumber(), not(0L)); - assertThat(plan.getMonthlyPriceInCents(), greaterThanOrEqualTo(0L)); + public void getRepository() throws IOException { + GHRepository repo = gitHub.getRepository("hub4j/github-api"); - // GHMarketplacePlan - list - assertThat(plan.getBullets().size(), equalTo(2)); + assertThat(repo.getFullName(), equalTo("hub4j/github-api")); - GHMarketplaceAccount account = userPurchase.getAccount(); - // GHMarketplaceAccount - Non-nullable fields - assertThat(account.getLogin(), notNullValue()); - assertThat(account.getUrl(), notNullValue()); - assertThat(account.getType(), notNullValue()); + GHRepository repo2 = gitHub.getRepositoryById(repo.getId()); + assertThat(repo2.getFullName(), equalTo("hub4j/github-api")); - // GHMarketplaceAccount - primitive fields - assertThat(account.getId(), not(0L)); + try { + gitHub.getRepository("hub4j_github-api"); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), equalTo("Repository name must be in format owner/repo")); + } - /* logical combination tests */ - // Rationale: organization_billing_email is only set when account type is ORGANIZATION. - if (account.getType() == ORGANIZATION) - assertThat(account.getOrganizationBillingEmail(), notNullValue()); - else - assertThat(account.getOrganizationBillingEmail(), nullValue()); + try { + gitHub.getRepository("hub4j/github/api"); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e.getMessage(), equalTo("Repository name must be in format owner/repo")); } } @@ -149,81 +97,43 @@ public void getOrgs() throws IOException { } /** - * Gets the repository. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void getRepository() throws IOException { - GHRepository repo = gitHub.getRepository("hub4j/github-api"); - - assertThat(repo.getFullName(), equalTo("hub4j/github-api")); - - GHRepository repo2 = gitHub.getRepositoryById(repo.getId()); - assertThat(repo2.getFullName(), equalTo("hub4j/github-api")); - - try { - gitHub.getRepository("hub4j_github-api"); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), equalTo("Repository name must be in format owner/repo")); - } - - try { - gitHub.getRepository("hub4j/github/api"); - fail(); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), equalTo("Repository name must be in format owner/repo")); - } - } - - /** - * Gzip. + * Search users. * * @throws Exception * the exception */ @Test - public void gzip() throws Exception { - - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - - // getResponseHeaderFields is deprecated but we'll use it for testing. - assertThat(org.getResponseHeaderFields(), notNullValue()); - - // WireMock should automatically gzip all responses - assertThat(org.getResponseHeaderFields().get("Content-Encoding").get(0), is("gzip")); - assertThat(org.getResponseHeaderFields().get("Content-eNcoding").get(0), is("gzip")); + public void searchUsers() throws Exception { + PagedSearchIterable r = gitHub.searchUsers().q("tom").repos(">42").followers(">1000").list(); + GHUser u = r.iterator().next(); + // System.out.println(u.getName()); + assertThat(u.getId(), notNullValue()); + assertThat(r.getTotalCount(), greaterThan(0)); } /** - * Verifies that the `type` field is correctly fetched when listing organizations. - *

- * Since the `type` field is not included by default in the list of organizations, this test ensures that calling - * {@code getType()} retrieves the expected value. - *

+ * Test list all repositories. * - * @throws IOException - * if an I/O error occurs while fetching the organizations. + * @throws Exception + * the exception */ @Test - public void listOrganizationsFetchesType() throws IOException { - String type = gitHub.listOrganizations().withPageSize(1).iterator().next().getType(); - assertThat(type, equalTo("Organization")); - } + public void testListAllRepositories() throws Exception { + Iterator itr = gitHub.listAllPublicRepositories().iterator(); + for (int i = 0; i < 115; i++) { + assertThat(itr.hasNext(), is(true)); + GHRepository r = itr.next(); + // System.out.println(r.getFullName()); + assertThat(r.getUrl(), notNullValue()); + assertThat(r.getId(), not(0L)); + } - /** - * List users. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void listUsers() throws IOException { - for (GHUser u : Iterables.limit(gitHub.listUsers(), 10)) { - assert u.getName() != null; - // System.out.println(u.getName()); + // ensure the iterator throws as expected + try { + itr.remove(); + fail(); + } catch (UnsupportedOperationException e) { + assertThat(e, notNullValue()); } } @@ -244,10 +154,6 @@ public void searchContent() throws Exception { .order(GHDirection.DESC) .list(); GHContent c = r.iterator().next(); - assertThat(c.getGitUrl(), endsWith("/repositories/167174/git/blobs/796fbcc808ca15bbe771f8c9c1a7bab3388f6128")); - assertThat(c.getHtmlUrl(), - endsWith( - "https://github.com/jquery/jquery/blob/a684e6ba836f7c553968d7d026ed7941e1a612d8/src/attributes/classes.js")); // System.out.println(c.getName()); assertThat(c.getDownloadUrl(), notNullValue()); @@ -353,33 +259,129 @@ public void searchContentWithForks() { } /** - * Search users. + * Test list my authorizations. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void searchUsers() { - PagedSearchIterable r = gitHub.searchUsers().q("tom").repos(">42").followers(">1000").list(); - GHUser u = r.iterator().next(); - // System.out.println(u.getName()); - assertThat(u.getId(), notNullValue()); - assertThat(r.getTotalCount(), greaterThan(0)); + public void testListMyAuthorizations() throws IOException { + PagedIterable list = gitHub.listMyAuthorizations(); + + for (GHAuthorization auth : list) { + assertThat(auth.getAppName(), notNullValue()); + } } /** - * Test expect GitHub {@link ServiceDownException} + * Gets the meta. * + * @throws IOException + * Signals that an I/O exception has occurred. */ @Test - public void testCatchServiceDownException() { - snapshotNotAllowed(); - try { - GHRepository repo = gitHub.getRepository("hub4j-test-org/github-api"); - repo.getFileContent("ghcontent-ro/service-down"); - fail("Exception was expected"); - } catch (IOException e) { - assertThat(e.getClass().getName(), equalToIgnoringCase(ServiceDownException.class.getName())); + public void getMeta() throws IOException { + GHMeta meta = gitHub.getMeta(); + assertThat(meta.isVerifiablePasswordAuthentication(), is(true)); + assertThat(meta.getApi().size(), equalTo(19)); + assertThat(meta.getGit().size(), equalTo(36)); + assertThat(meta.getHooks().size(), equalTo(4)); + assertThat(meta.getImporter().size(), equalTo(3)); + assertThat(meta.getPages().size(), equalTo(6)); + assertThat(meta.getWeb().size(), equalTo(20)); + assertThat(meta.getPackages().size(), equalTo(25)); + assertThat(meta.getActions().size(), equalTo(1739)); + assertThat(meta.getDependabot().size(), equalTo(3)); + + // Also test examples here + Class[] examples = new Class[]{ ReadOnlyObjects.GHMetaPublic.class, ReadOnlyObjects.GHMetaPackage.class, + ReadOnlyObjects.GHMetaGettersUnmodifiable.class, ReadOnlyObjects.GHMetaGettersFinal.class, + ReadOnlyObjects.GHMetaGettersFinalCreator.class, }; + + for (Class metaClass : examples) { + ReadOnlyObjects.GHMetaExample metaExample = gitHub.createRequest() + .withUrlPath("/meta") + .fetch((Class) metaClass); + assertThat(metaExample.isVerifiablePasswordAuthentication(), is(true)); + assertThat(metaExample.getApi().size(), equalTo(19)); + assertThat(metaExample.getGit().size(), equalTo(36)); + assertThat(metaExample.getHooks().size(), equalTo(4)); + assertThat(metaExample.getImporter().size(), equalTo(3)); + assertThat(metaExample.getPages().size(), equalTo(6)); + assertThat(metaExample.getWeb().size(), equalTo(20)); + } + } + + /** + * Gets the my marketplace purchases. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void getMyMarketplacePurchases() throws IOException { + List userPurchases = gitHub.getMyMarketplacePurchases().toList(); + assertThat(userPurchases.size(), equalTo(2)); + + for (GHMarketplaceUserPurchase userPurchase : userPurchases) { + assertThat(userPurchase.isOnFreeTrial(), is(false)); + assertThat(userPurchase.getFreeTrialEndsOn(), nullValue()); + assertThat(userPurchase.getBillingCycle(), equalTo("monthly")); + + GHMarketplacePlan plan = userPurchase.getPlan(); + // GHMarketplacePlan - Non-nullable fields + assertThat(plan.getUrl(), notNullValue()); + assertThat(plan.getAccountsUrl(), notNullValue()); + assertThat(plan.getName(), notNullValue()); + assertThat(plan.getDescription(), notNullValue()); + assertThat(plan.getPriceModel(), notNullValue()); + assertThat(plan.getState(), notNullValue()); + + // GHMarketplacePlan - primitive fields + assertThat(plan.getId(), not(0L)); + assertThat(plan.getNumber(), not(0L)); + assertThat(plan.getMonthlyPriceInCents(), greaterThanOrEqualTo(0L)); + + // GHMarketplacePlan - list + assertThat(plan.getBullets().size(), equalTo(2)); + + GHMarketplaceAccount account = userPurchase.getAccount(); + // GHMarketplaceAccount - Non-nullable fields + assertThat(account.getLogin(), notNullValue()); + assertThat(account.getUrl(), notNullValue()); + assertThat(account.getType(), notNullValue()); + + // GHMarketplaceAccount - primitive fields + assertThat(account.getId(), not(0L)); + + /* logical combination tests */ + // Rationale: organization_billing_email is only set when account type is ORGANIZATION. + if (account.getType() == ORGANIZATION) + assertThat(account.getOrganizationBillingEmail(), notNullValue()); + else + assertThat(account.getOrganizationBillingEmail(), nullValue()); } } + /** + * Gzip. + * + * @throws Exception + * the exception + */ + @Test + public void gzip() throws Exception { + + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + + // getResponseHeaderFields is deprecated but we'll use it for testing. + assertThat(org.getResponseHeaderFields(), notNullValue()); + + // WireMock should automatically gzip all responses + assertThat(org.getResponseHeaderFields().get("Content-Encoding").get(0), is("gzip")); + assertThat(org.getResponseHeaderFields().get("Content-eNcoding").get(0), is("gzip")); + } + /** * Test header field name. * @@ -403,37 +405,18 @@ public void testHeaderFieldName() throws Exception { } /** - * Test list all repositories. + * Test expect GitHub {@link ServiceDownException} + * */ @Test - public void testListAllRepositories() { - Iterator itr = gitHub.listAllPublicRepositories().iterator(); - for (int i = 0; i < 115; i++) { - assertThat(itr.hasNext(), is(true)); - GHRepository r = itr.next(); - // System.out.println(r.getFullName()); - assertThat(r.getUrl(), notNullValue()); - assertThat(r.getId(), not(0L)); - } - - // ensure the iterator throws as expected + public void testCatchServiceDownException() { + snapshotNotAllowed(); try { - itr.remove(); - fail(); - } catch (UnsupportedOperationException e) { - assertThat(e, notNullValue()); - } - } - - /** - * Test list my authorizations. - */ - @Test - public void testListMyAuthorizations() { - PagedIterable list = gitHub.listMyAuthorizations(); - - for (GHAuthorization auth : list) { - assertThat(auth.getAppName(), notNullValue()); + GHRepository repo = gitHub.getRepository("hub4j-test-org/github-api"); + repo.getFileContent("ghcontent-ro/service-down"); + fail("Exception was expected"); + } catch (IOException e) { + assertThat(e.getClass().getName(), equalToIgnoringCase(ServiceDownException.class.getName())); } } } diff --git a/src/test/java/org/kohsuke/github/GitHubWireMockRule.java b/src/test/java/org/kohsuke/github/GitHubWireMockRule.java index e78790ed32..bd4224f9dc 100644 --- a/src/test/java/org/kohsuke/github/GitHubWireMockRule.java +++ b/src/test/java/org/kohsuke/github/GitHubWireMockRule.java @@ -39,213 +39,29 @@ */ public class GitHubWireMockRule extends WireMockMultiServerRule { - /** - * A number of modifications are needed as runtime to make responses target the WireMock server and not accidentally - * switch to using the live github servers. - */ - private static class GitHubApiResponseTransformer extends ResponseTransformer { - private final GitHubWireMockRule rule; - - public GitHubApiResponseTransformer(GitHubWireMockRule rule) { - this.rule = rule; - } - - @Override - public String getName() { - return "github-api-url-rewrite"; - } - - @Override - public Response transform(Request request, Response response, FileSource files, Parameters parameters) { - Response.Builder builder = Response.Builder.like(response); - Collection headers = response.getHeaders().all(); - - fixListTraversalHeader(response, headers); - fixLocationHeader(response, headers); - - if ("application/json".equals(response.getHeaders().getContentTypeHeader().mimeTypePart())) { - - String body; - body = getBodyAsString(response, headers); - body = rule.mapToMockGitHub(body); - - builder.body(body); - - } - builder.headers(new HttpHeaders(headers)); - - return builder.build(); - } - - private void fixListTraversalHeader(Response response, Collection headers) { - // Lists are broken up into pages. The Link header contains urls for previous and next pages. - HttpHeader linkHeader = response.getHeaders().getHeader("Link"); - if (linkHeader.isPresent()) { - headers.removeIf(item -> item.keyEquals("Link")); - headers.add(HttpHeader.httpHeader("Link", rule.mapToMockGitHub(linkHeader.firstValue()))); - } - } - - private void fixLocationHeader(Response response, Collection headers) { - // For redirects, the Location header points to the new target. - HttpHeader locationHeader = response.getHeaders().getHeader("Location"); - if (locationHeader.isPresent()) { - String originalLocationHeaderValue = locationHeader.firstValue(); - String rewrittenLocationHeaderValue = rule.mapToMockGitHub(originalLocationHeaderValue); - - headers.removeIf(item -> item.keyEquals("Location")); - - // in the case of the blob.core.windows.net server, we need to keep the original host around - // as the host name is dynamic - // this is a hack as we pass the original host as an additional parameter which will - // end up in the request we push to the GitHub server but that is the best we can do - // given Wiremock's infrastructure - Matcher matcher = BLOB_CORE_WINDOWS_PATTERN.matcher(originalLocationHeaderValue); - if (matcher.find() && rule.isUseProxy()) { - rewrittenLocationHeaderValue += "&" + ORIGINAL_HOST + "=" + matcher.group(1); - } - - headers.add(HttpHeader.httpHeader("Location", rewrittenLocationHeaderValue)); - } - } - - private String getBodyAsString(Response response, Collection headers) { - String body; - if (response.getHeaders().getHeader("Content-Encoding").containsValue("gzip")) { - headers.removeIf(item -> item.keyEquals("Content-Encoding")); - body = unGzipToString(response.getBody()); - } else { - body = response.getBodyAsString(); - } - return body; - } - } - private static class MappingFileDetails { - private static Path getPathWithShortenedFileName(Path filePath, String name, String insertionIndex) { - String extension = FilenameUtils.getExtension(filePath.getFileName().toString()); - // Add an underscore to the start and end for easier pattern matching. - String fileName = "_" + name + "_"; - - // Shorten early segments of the file name - // which tend to be repetative - "repos_hub4j-test-org_{repository}". - // also shorten multiple underscores in these segments - fileName = fileName.replaceAll("^_([a-zA-Z0-9])[^_]+_+([a-zA-Z0-9])[^_]+_+([a-zA-Z0-9])[^_]+_+([^_])", - "_$1_$2_$3_$4"); - fileName = fileName.replaceAll("^_([a-zA-Z0-9])[^_]+_+([a-zA-Z0-9])[^_]+_+([^_])", "_$1_$2_$3"); - - // Any remaining segment that longer the 32 characters, truncate to 8 - fileName = fileName.replaceAll("_([^_]{8})[^_]{23}[^_]+_", "_$1_"); - - // If the file name is still longer than 60 characters, truncate it - fileName = fileName.replaceAll("^_(.{60}).+_$", "_$1_"); - - // Remove outer underscores - fileName = fileName.substring(1, fileName.length() - 1); - Path targetPath = filePath.resolveSibling(insertionIndex + "-" + fileName + "." + extension); - - return targetPath; - } - final Path bodyPath; // body file from the mapping file contents - final Path filePath; - final Path renamedBodyPath; - - final Path renamedFilePath; - - MappingFileDetails(Path filePath, Map parsedObject) { - this.filePath = filePath; - String insertionIndex = Long - .toString(((Double) parsedObject.getOrDefault("insertionIndex", 0.0)).longValue()); - - String name = (String) parsedObject.get("name"); - if (name == null) { - // if name is not present, use url and id to generate a name - Map request = (Map) parsedObject.get("request"); - // ignore - name = ((String) request.get("url")).split("[?]")[0].replaceAll("_", "-").replaceAll("[\\\\/]", "_"); - if (name.startsWith("_")) { - name = name.substring(1); - } - name += "_" + (String) parsedObject.get("id"); - } - - this.renamedFilePath = getPathWithShortenedFileName(this.filePath, name, insertionIndex); - - Map responseObject = (Map) parsedObject.get("response"); - String bodyFileName = responseObject == null ? null : (String) responseObject.get("bodyFileName"); - if (bodyFileName != null) { - this.bodyPath = filePath.getParent().resolveSibling("__files").resolve(bodyFileName); - this.renamedBodyPath = getPathWithShortenedFileName(this.bodyPath, name, insertionIndex); - } else { - this.bodyPath = null; - this.renamedBodyPath = null; - } - } - - void renameFiles() throws IOException { - if (!filePath.equals(renamedFilePath)) { - Files.move(filePath, renamedFilePath); - } - if (bodyPath != null && !bodyPath.equals(renamedBodyPath)) { - Files.move(bodyPath, renamedBodyPath); - } - } - } - private static class ProxyToOriginalHostTransformer extends ResponseDefinitionTransformer { - - private static final String NAME = "proxy-to-original-host"; - - private final GitHubWireMockRule rule; - - private ProxyToOriginalHostTransformer(GitHubWireMockRule rule) { - this.rule = rule; - } - - @Override - public String getName() { - return NAME; - } - - @Override - public ResponseDefinition transform(Request request, - ResponseDefinition responseDefinition, - FileSource files, - Parameters parameters) { - if (!rule.isUseProxy() || !request.queryParameter(ORIGINAL_HOST).isPresent()) { - return responseDefinition; - } - - String originalHost = request.queryParameter(ORIGINAL_HOST).firstValue(); - - return ResponseDefinitionBuilder.like(responseDefinition).proxiedFrom("https://" + originalHost).build(); - } - } - - private final static Pattern ACTIONS_USER_CONTENT_PATTERN = Pattern - .compile("https://pipelines[a-z0-9]*\\.actions\\.githubusercontent\\.com", Pattern.CASE_INSENSITIVE); - private final static Pattern BLOB_CORE_WINDOWS_PATTERN = Pattern - .compile("https://([a-z0-9]*\\.blob\\.core\\.windows\\.net)", Pattern.CASE_INSENSITIVE); - private final static String ORIGINAL_HOST = "originalHost"; - // By default the wiremock tests will run without proxy or taking a snapshot. // The tests will use only the stubbed data and will fail if requests are made for missing data. // You can use the proxy without taking a snapshot while writing and debugging tests. // You cannot take a snapshot without proxying. private final static boolean takeSnapshot = System.getProperty("test.github.takeSnapshot", "false") != "false"; - private final static boolean testWithOrg = System.getProperty("test.github.org", "true") == "true"; - private final static boolean useProxy = takeSnapshot || System.getProperty("test.github.useProxy", "false") != "false"; + private final static Pattern ACTIONS_USER_CONTENT_PATTERN = Pattern + .compile("https://pipelines[a-z0-9]*\\.actions\\.githubusercontent\\.com", Pattern.CASE_INSENSITIVE); + private final static Pattern BLOB_CORE_WINDOWS_PATTERN = Pattern + .compile("https://([a-z0-9]*\\.blob\\.core\\.windows\\.net)", Pattern.CASE_INSENSITIVE); + private final static String ORIGINAL_HOST = "originalHost"; + /** - * Gets the request count. + * Customize record spec. * - * @param server - * the server - * @return the request count + * @param customizeRecordSpec + * the customize record spec */ - public static int getRequestCount(WireMockServer server) { - return server.countRequestsMatching(RequestPatternBuilder.allRequests().build()).getCount(); + public void customizeRecordSpec(Consumer customizeRecordSpec) { + this.customizeRecordSpec = customizeRecordSpec; } private Consumer customizeRecordSpec = null; @@ -280,30 +96,30 @@ public GitHubWireMockRule(WireMockConfiguration options, boolean failOnUnmatched } /** - * Actions user content server. + * Api server. * * @return the wire mock server */ - public WireMockServer actionsUserContentServer() { - return servers.get("actions-user-content"); + public WireMockServer apiServer() { + return servers.get("default"); } /** - * Api server. + * Raw server. * * @return the wire mock server */ - public WireMockServer apiServer() { - return servers.get("default"); + public WireMockServer rawServer() { + return servers.get("raw"); } /** - * Actions user content server. + * Uploads server. * * @return the wire mock server */ - public WireMockServer blobCoreWindowsNetServer() { - return servers.get("blob-core-windows-net"); + public WireMockServer uploadsServer() { + return servers.get("uploads"); } /** @@ -316,22 +132,30 @@ public WireMockServer codeloadServer() { } /** - * Customize record spec. + * Actions user content server. * - * @param customizeRecordSpec - * the customize record spec + * @return the wire mock server */ - public void customizeRecordSpec(Consumer customizeRecordSpec) { - this.customizeRecordSpec = customizeRecordSpec; + public WireMockServer actionsUserContentServer() { + return servers.get("actions-user-content"); } /** - * Gets the request count. + * Actions user content server. * - * @return the request count + * @return the wire mock server */ - public int getRequestCount() { - return getRequestCount(apiServer()); + public WireMockServer blobCoreWindowsNetServer() { + return servers.get("blob-core-windows-net"); + } + + /** + * Checks if is use proxy. + * + * @return true, if is use proxy + */ + public boolean isUseProxy() { + return GitHubWireMockRule.useProxy; } /** @@ -353,99 +177,213 @@ public boolean isTestWithOrg() { } /** - * Checks if is use proxy. - * - * @return true, if is use proxy + * Initialize servers. */ - public boolean isUseProxy() { - return GitHubWireMockRule.useProxy; + @Override + protected void initializeServers() { + super.initializeServers(); + initializeServer("default", new GitHubApiResponseTransformer(this)); + + // only start non-api servers if we might need them + if (new File(apiServer().getOptions().filesRoot().getPath() + "_raw").exists() || isUseProxy()) { + initializeServer("raw"); + } + if (new File(apiServer().getOptions().filesRoot().getPath() + "_uploads").exists() || isUseProxy()) { + initializeServer("uploads"); + } + + if (new File(apiServer().getOptions().filesRoot().getPath() + "_codeload").exists() || isUseProxy()) { + initializeServer("codeload"); + } + + if (new File(apiServer().getOptions().filesRoot().getPath() + "_actions-user-content").exists() + || isUseProxy()) { + initializeServer("actions-user-content"); + } + + if (new File(apiServer().getOptions().filesRoot().getPath() + "_blob-core-windows-net").exists() + || isUseProxy()) { + initializeServer("blob-core-windows-net", new ProxyToOriginalHostTransformer(this)); + } } /** - * Map to mock git hub. - * - * @param body - * the body - * @return the string + * Before. */ - @Nonnull - public String mapToMockGitHub(String body) { - body = body.replace("https://api.github.com", this.apiServer().baseUrl()); + @Override + protected void before() { + super.before(); + if (!isUseProxy()) { + return; + } - body = replaceTargetServerUrl(body, this.rawServer(), "https://raw.githubusercontent.com", "/raw"); + this.apiServer().stubFor(proxyAllTo("https://api.github.com").atPriority(100)); - body = replaceTargetServerUrl(body, this.uploadsServer(), "https://uploads.github.com", "/uploads"); + if (this.rawServer() != null) { + this.rawServer().stubFor(proxyAllTo("https://raw.githubusercontent.com").atPriority(100)); + } - body = replaceTargetServerUrl(body, this.codeloadServer(), "https://codeload.github.com", "/codeload"); + if (this.uploadsServer() != null) { + this.uploadsServer().stubFor(proxyAllTo("https://uploads.github.com").atPriority(100)); + } - body = replaceTargetServerUrl(body, - this.actionsUserContentServer(), - ACTIONS_USER_CONTENT_PATTERN, - "/actions-user-content"); + if (this.codeloadServer() != null) { + this.codeloadServer().stubFor(proxyAllTo("https://codeload.github.com").atPriority(100)); + } - body = replaceTargetServerUrl(body, - this.blobCoreWindowsNetServer(), - BLOB_CORE_WINDOWS_PATTERN, - "/blob-core-windows-net"); + if (this.actionsUserContentServer() != null) { + this.actionsUserContentServer() + .stubFor(proxyAllTo("https://pipelines.actions.githubusercontent.com").atPriority(100)); + } - return body; + if (this.blobCoreWindowsNetServer() != null) { + this.blobCoreWindowsNetServer() + .stubFor(any(anyUrl()).willReturn(aResponse().withTransformers(ProxyToOriginalHostTransformer.NAME)) + .atPriority(100)); + } } /** - * Raw server. + * After. + */ + @Override + protected void after() { + super.after(); + if (!isTakeSnapshot()) { + return; + } + + recordSnapshot(this.apiServer(), "https://api.github.com", false); + + // For raw server, only fix up mapping files + recordSnapshot(this.rawServer(), "https://raw.githubusercontent.com", true); + + recordSnapshot(this.uploadsServer(), "https://uploads.github.com", false); + + recordSnapshot(this.codeloadServer(), "https://codeload.github.com", true); + + recordSnapshot(this.actionsUserContentServer(), "https://pipelines.actions.githubusercontent.com", true); + + recordSnapshot(this.blobCoreWindowsNetServer(), "https://productionresults.blob.core.windows.net", true); + } + + private void recordSnapshot(WireMockServer server, String target, boolean isRawServer) { + if (server != null) { + + final RecordSpecBuilder recordSpecBuilder = recordSpec().forTarget(target) + // "If-None-Match" header used for ETag matching for caching connections + .captureHeader("If-None-Match") + // "If-Modified-Since" header used for ETag matching for caching connections + .captureHeader("If-Modified-Since") + .captureHeader("Cache-Control") + // "Accept" header is used to specify previews. If it changes expected data may not be retrieved. + .captureHeader("Accept") + // This is required, or some requests will return data from unexpected stubs + // For example, if you update "title" and "body", and then update just "title" to the same value + // the mock framework will treat those two requests as equivalent, which we do not want. + .chooseBodyMatchTypeAutomatically(true, false, false) + .extractTextBodiesOver(255); + + if (customizeRecordSpec != null) { + customizeRecordSpec.accept(recordSpecBuilder); + } + + server.snapshotRecord(recordSpecBuilder); + + // After taking the snapshot, format the output + formatTestResources(new File(server.getOptions().filesRoot().getPath()).toPath(), isRawServer); + } + } + + /** + * Gets the request count. * - * @return the wire mock server + * @return the request count */ - public WireMockServer rawServer() { - return servers.get("raw"); + public int getRequestCount() { + return getRequestCount(apiServer()); } /** - * Uploads server. + * Gets the request count. * - * @return the wire mock server + * @param server + * the server + * @return the request count */ - public WireMockServer uploadsServer() { - return servers.get("uploads"); + public static int getRequestCount(WireMockServer server) { + return server.countRequestsMatching(RequestPatternBuilder.allRequests().build()).getCount(); } - private void fixJsonContents(Gson g, Path filePath, Path bodyPath, Path renamedBodyPath) throws IOException { - String fileText = new String(Files.readAllBytes(filePath)); - // while recording responses we replaced all github calls localhost - // now we reverse that for storage. - fileText = fileText.replace(this.apiServer().baseUrl(), "https://api.github.com"); + private static class MappingFileDetails { + final Path filePath; + final Path bodyPath; // body file from the mapping file contents + final Path renamedFilePath; + final Path renamedBodyPath; - if (this.rawServer() != null) { - fileText = fileText.replace(this.rawServer().baseUrl(), "https://raw.githubusercontent.com"); - } + MappingFileDetails(Path filePath, Map parsedObject) { + this.filePath = filePath; + String insertionIndex = Long + .toString(((Double) parsedObject.getOrDefault("insertionIndex", 0.0)).longValue()); - if (this.uploadsServer() != null) { - fileText = fileText.replace(this.uploadsServer().baseUrl(), "https://uploads.github.com"); - } + String name = (String) parsedObject.get("name"); + if (name == null) { + // if name is not present, use url and id to generate a name + Map request = (Map) parsedObject.get("request"); + // ignore + name = ((String) request.get("url")).split("[?]")[0].replaceAll("_", "-").replaceAll("[\\\\/]", "_"); + if (name.startsWith("_")) { + name = name.substring(1); + } + name += "_" + (String) parsedObject.get("id"); + } - if (this.codeloadServer() != null) { - fileText = fileText.replace(this.codeloadServer().baseUrl(), "https://codeload.github.com"); + this.renamedFilePath = getPathWithShortenedFileName(this.filePath, name, insertionIndex); + + Map responseObject = (Map) parsedObject.get("response"); + String bodyFileName = responseObject == null ? null : (String) responseObject.get("bodyFileName"); + if (bodyFileName != null) { + this.bodyPath = filePath.getParent().resolveSibling("__files").resolve(bodyFileName); + this.renamedBodyPath = getPathWithShortenedFileName(this.bodyPath, name, insertionIndex); + } else { + this.bodyPath = null; + this.renamedBodyPath = null; + } } - if (this.actionsUserContentServer() != null) { - fileText = fileText.replace(this.actionsUserContentServer().baseUrl(), - "https://pipelines.actions.githubusercontent.com"); + void renameFiles() throws IOException { + if (!filePath.equals(renamedFilePath)) { + Files.move(filePath, renamedFilePath); + } + if (bodyPath != null && !bodyPath.equals(renamedBodyPath)) { + Files.move(bodyPath, renamedBodyPath); + } } - if (this.blobCoreWindowsNetServer() != null) { - fileText = fileText.replace(this.blobCoreWindowsNetServer().baseUrl(), - "https://productionresults.blob.core.windows.net"); - } + private static Path getPathWithShortenedFileName(Path filePath, String name, String insertionIndex) { + String extension = FilenameUtils.getExtension(filePath.getFileName().toString()); + // Add an underscore to the start and end for easier pattern matching. + String fileName = "_" + name + "_"; + + // Shorten early segments of the file name + // which tend to be repetative - "repos_hub4j-test-org_{repository}". + // also shorten multiple underscores in these segments + fileName = fileName.replaceAll("^_([a-zA-Z0-9])[^_]+_+([a-zA-Z0-9])[^_]+_+([a-zA-Z0-9])[^_]+_+([^_])", + "_$1_$2_$3_$4"); + fileName = fileName.replaceAll("^_([a-zA-Z0-9])[^_]+_+([a-zA-Z0-9])[^_]+_+([^_])", "_$1_$2_$3"); + + // Any remaining segment that longer the 32 characters, truncate to 8 + fileName = fileName.replaceAll("_([^_]{8})[^_]{23}[^_]+_", "_$1_"); + + // If the file name is still longer than 60 characters, truncate it + fileName = fileName.replaceAll("^_(.{60}).+_$", "_$1_"); - // point body file path to the renamed body file - if (bodyPath != null) { - fileText = fileText.replace(bodyPath.getFileName().toString(), renamedBodyPath.getFileName().toString()); - } + // Remove outer underscores + fileName = fileName.substring(1, fileName.length() - 1); + Path targetPath = filePath.resolveSibling(insertionIndex + "-" + fileName + "." + extension); - // Can be Array or Map - Object parsedObject = g.fromJson(fileText, Object.class); - String outputFileText = g.toJson(parsedObject); - Files.write(filePath, outputFileText.getBytes()); + return targetPath; + } } private void formatTestResources(Path path, boolean isRawServer) { @@ -527,146 +465,210 @@ public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContex } } - private void recordSnapshot(WireMockServer server, String target, boolean isRawServer) { - if (server != null) { + private void fixJsonContents(Gson g, Path filePath, Path bodyPath, Path renamedBodyPath) throws IOException { + String fileText = new String(Files.readAllBytes(filePath)); + // while recording responses we replaced all github calls localhost + // now we reverse that for storage. + fileText = fileText.replace(this.apiServer().baseUrl(), "https://api.github.com"); - final RecordSpecBuilder recordSpecBuilder = recordSpec().forTarget(target) - // "If-None-Match" header used for ETag matching for caching connections - .captureHeader("If-None-Match") - // "If-Modified-Since" header used for ETag matching for caching connections - .captureHeader("If-Modified-Since") - .captureHeader("Cache-Control") - // "Accept" header is used to specify previews. If it changes expected data may not be retrieved. - .captureHeader("Accept") - // This is required, or some requests will return data from unexpected stubs - // For example, if you update "title" and "body", and then update just "title" to the same value - // the mock framework will treat those two requests as equivalent, which we do not want. - .chooseBodyMatchTypeAutomatically(true, false, false) - .extractTextBodiesOver(255); + if (this.rawServer() != null) { + fileText = fileText.replace(this.rawServer().baseUrl(), "https://raw.githubusercontent.com"); + } - if (customizeRecordSpec != null) { - customizeRecordSpec.accept(recordSpecBuilder); - } + if (this.uploadsServer() != null) { + fileText = fileText.replace(this.uploadsServer().baseUrl(), "https://uploads.github.com"); + } - server.snapshotRecord(recordSpecBuilder); + if (this.codeloadServer() != null) { + fileText = fileText.replace(this.codeloadServer().baseUrl(), "https://codeload.github.com"); + } - // After taking the snapshot, format the output - formatTestResources(new File(server.getOptions().filesRoot().getPath()).toPath(), isRawServer); + if (this.actionsUserContentServer() != null) { + fileText = fileText.replace(this.actionsUserContentServer().baseUrl(), + "https://pipelines.actions.githubusercontent.com"); + } + + if (this.blobCoreWindowsNetServer() != null) { + fileText = fileText.replace(this.blobCoreWindowsNetServer().baseUrl(), + "https://productionresults.blob.core.windows.net"); + } + + // point body file path to the renamed body file + if (bodyPath != null) { + fileText = fileText.replace(bodyPath.getFileName().toString(), renamedBodyPath.getFileName().toString()); } + + // Can be Array or Map + Object parsedObject = g.fromJson(fileText, Object.class); + String outputFileText = g.toJson(parsedObject); + Files.write(filePath, outputFileText.getBytes()); + } + + /** + * Map to mock git hub. + * + * @param body + * the body + * @return the string + */ + @Nonnull + public String mapToMockGitHub(String body) { + body = body.replace("https://api.github.com", this.apiServer().baseUrl()); + + body = replaceTargetServerUrl(body, this.rawServer(), "https://raw.githubusercontent.com", "/raw"); + + body = replaceTargetServerUrl(body, this.uploadsServer(), "https://uploads.github.com", "/uploads"); + + body = replaceTargetServerUrl(body, this.codeloadServer(), "https://codeload.github.com", "/codeload"); + + body = replaceTargetServerUrl(body, + this.actionsUserContentServer(), + ACTIONS_USER_CONTENT_PATTERN, + "/actions-user-content"); + + body = replaceTargetServerUrl(body, + this.blobCoreWindowsNetServer(), + BLOB_CORE_WINDOWS_PATTERN, + "/blob-core-windows-net"); + + return body; } - @NonNull private String replaceTargetServerUrl(String body, + @NonNull + private String replaceTargetServerUrl(String body, WireMockServer wireMockServer, - Pattern regexp, + String rawTarget, String inactiveTarget) { if (wireMockServer != null) { - body = regexp.matcher(body).replaceAll(wireMockServer.baseUrl()); + body = body.replace(rawTarget, wireMockServer.baseUrl()); } else { - body = regexp.matcher(body).replaceAll(this.apiServer().baseUrl() + inactiveTarget); + body = body.replace(rawTarget, this.apiServer().baseUrl() + inactiveTarget); } return body; } - @NonNull private String replaceTargetServerUrl(String body, + @NonNull + private String replaceTargetServerUrl(String body, WireMockServer wireMockServer, - String rawTarget, + Pattern regexp, String inactiveTarget) { if (wireMockServer != null) { - body = body.replace(rawTarget, wireMockServer.baseUrl()); + body = regexp.matcher(body).replaceAll(wireMockServer.baseUrl()); } else { - body = body.replace(rawTarget, this.apiServer().baseUrl() + inactiveTarget); + body = regexp.matcher(body).replaceAll(this.apiServer().baseUrl() + inactiveTarget); } return body; } /** - * After. + * A number of modifications are needed as runtime to make responses target the WireMock server and not accidentally + * switch to using the live github servers. */ - @Override - protected void after() { - super.after(); - if (!isTakeSnapshot()) { - return; + private static class GitHubApiResponseTransformer extends ResponseTransformer { + private final GitHubWireMockRule rule; + + public GitHubApiResponseTransformer(GitHubWireMockRule rule) { + this.rule = rule; } - recordSnapshot(this.apiServer(), "https://api.github.com", false); + @Override + public Response transform(Request request, Response response, FileSource files, Parameters parameters) { + Response.Builder builder = Response.Builder.like(response); + Collection headers = response.getHeaders().all(); - // For raw server, only fix up mapping files - recordSnapshot(this.rawServer(), "https://raw.githubusercontent.com", true); + fixListTraversalHeader(response, headers); + fixLocationHeader(response, headers); - recordSnapshot(this.uploadsServer(), "https://uploads.github.com", false); + if ("application/json".equals(response.getHeaders().getContentTypeHeader().mimeTypePart())) { - recordSnapshot(this.codeloadServer(), "https://codeload.github.com", true); + String body; + body = getBodyAsString(response, headers); + body = rule.mapToMockGitHub(body); - recordSnapshot(this.actionsUserContentServer(), "https://pipelines.actions.githubusercontent.com", true); + builder.body(body); - recordSnapshot(this.blobCoreWindowsNetServer(), "https://productionresults.blob.core.windows.net", true); - } + } + builder.headers(new HttpHeaders(headers)); - /** - * Before. - */ - @Override - protected void before() { - super.before(); - if (!isUseProxy()) { - return; + return builder.build(); } - this.apiServer().stubFor(proxyAllTo("https://api.github.com").atPriority(100)); - - if (this.rawServer() != null) { - this.rawServer().stubFor(proxyAllTo("https://raw.githubusercontent.com").atPriority(100)); + private String getBodyAsString(Response response, Collection headers) { + String body; + if (response.getHeaders().getHeader("Content-Encoding").containsValue("gzip")) { + headers.removeIf(item -> item.keyEquals("Content-Encoding")); + body = unGzipToString(response.getBody()); + } else { + body = response.getBodyAsString(); + } + return body; } - if (this.uploadsServer() != null) { - this.uploadsServer().stubFor(proxyAllTo("https://uploads.github.com").atPriority(100)); + private void fixListTraversalHeader(Response response, Collection headers) { + // Lists are broken up into pages. The Link header contains urls for previous and next pages. + HttpHeader linkHeader = response.getHeaders().getHeader("Link"); + if (linkHeader.isPresent()) { + headers.removeIf(item -> item.keyEquals("Link")); + headers.add(HttpHeader.httpHeader("Link", rule.mapToMockGitHub(linkHeader.firstValue()))); + } } - if (this.codeloadServer() != null) { - this.codeloadServer().stubFor(proxyAllTo("https://codeload.github.com").atPriority(100)); - } + private void fixLocationHeader(Response response, Collection headers) { + // For redirects, the Location header points to the new target. + HttpHeader locationHeader = response.getHeaders().getHeader("Location"); + if (locationHeader.isPresent()) { + String originalLocationHeaderValue = locationHeader.firstValue(); + String rewrittenLocationHeaderValue = rule.mapToMockGitHub(originalLocationHeaderValue); - if (this.actionsUserContentServer() != null) { - this.actionsUserContentServer() - .stubFor(proxyAllTo("https://pipelines.actions.githubusercontent.com").atPriority(100)); + headers.removeIf(item -> item.keyEquals("Location")); + + // in the case of the blob.core.windows.net server, we need to keep the original host around + // as the host name is dynamic + // this is a hack as we pass the original host as an additional parameter which will + // end up in the request we push to the GitHub server but that is the best we can do + // given Wiremock's infrastructure + Matcher matcher = BLOB_CORE_WINDOWS_PATTERN.matcher(originalLocationHeaderValue); + if (matcher.find() && rule.isUseProxy()) { + rewrittenLocationHeaderValue += "&" + ORIGINAL_HOST + "=" + matcher.group(1); + } + + headers.add(HttpHeader.httpHeader("Location", rewrittenLocationHeaderValue)); + } } - if (this.blobCoreWindowsNetServer() != null) { - this.blobCoreWindowsNetServer() - .stubFor(any(anyUrl()).willReturn(aResponse().withTransformers(ProxyToOriginalHostTransformer.NAME)) - .atPriority(100)); + @Override + public String getName() { + return "github-api-url-rewrite"; } } - /** - * Initialize servers. - */ - @Override - protected void initializeServers() { - super.initializeServers(); - initializeServer("default", new GitHubApiResponseTransformer(this)); + private static class ProxyToOriginalHostTransformer extends ResponseDefinitionTransformer { - // only start non-api servers if we might need them - if (new File(apiServer().getOptions().filesRoot().getPath() + "_raw").exists() || isUseProxy()) { - initializeServer("raw"); - } - if (new File(apiServer().getOptions().filesRoot().getPath() + "_uploads").exists() || isUseProxy()) { - initializeServer("uploads"); - } + private static final String NAME = "proxy-to-original-host"; - if (new File(apiServer().getOptions().filesRoot().getPath() + "_codeload").exists() || isUseProxy()) { - initializeServer("codeload"); + private final GitHubWireMockRule rule; + + private ProxyToOriginalHostTransformer(GitHubWireMockRule rule) { + this.rule = rule; } - if (new File(apiServer().getOptions().filesRoot().getPath() + "_actions-user-content").exists() - || isUseProxy()) { - initializeServer("actions-user-content"); + @Override + public String getName() { + return NAME; } - if (new File(apiServer().getOptions().filesRoot().getPath() + "_blob-core-windows-net").exists() - || isUseProxy()) { - initializeServer("blob-core-windows-net", new ProxyToOriginalHostTransformer(this)); + @Override + public ResponseDefinition transform(Request request, + ResponseDefinition responseDefinition, + FileSource files, + Parameters parameters) { + if (!rule.isUseProxy() || !request.queryParameter(ORIGINAL_HOST).isPresent()) { + return responseDefinition; + } + + String originalHost = request.queryParameter(ORIGINAL_HOST).firstValue(); + + return ResponseDefinitionBuilder.like(responseDefinition).proxiedFrom("https://" + originalHost).build(); } } } diff --git a/src/test/java/org/kohsuke/github/LifecycleTest.java b/src/test/java/org/kohsuke/github/LifecycleTest.java index efa9335c8f..b518fb6444 100644 --- a/src/test/java/org/kohsuke/github/LifecycleTest.java +++ b/src/test/java/org/kohsuke/github/LifecycleTest.java @@ -59,15 +59,33 @@ public void testCreateRepository() throws IOException { deleteAsset(release, asset); } - private File createDummyFile(File repoDir) throws IOException { - File file = new File(repoDir, "testFile-" + System.currentTimeMillis()); - PrintWriter writer = new PrintWriter(new FileWriter(file)); - try { - writer.println("test file"); - } finally { - writer.close(); - } - return file; + private void updateAsset(GHRelease release, GHAsset asset) throws IOException { + asset.setLabel("test label"); + assertThat(release.listAssets().toList().get(0).getLabel(), equalTo("test label")); + } + + private void deleteAsset(GHRelease release, GHAsset asset) throws IOException { + asset.delete(); + assertThat(release.listAssets().toList(), is(empty())); + } + + private GHAsset uploadAsset(GHRelease release) throws IOException { + GHAsset asset = release.uploadAsset(new File("LICENSE.txt"), "application/text"); + assertThat(asset, notNullValue()); + List cachedAssets = release.getAssets(); + assertThat(cachedAssets, is(empty())); + List assets = release.listAssets().toList(); + assertThat(assets.size(), equalTo(1)); + assertThat(assets.get(0).getName(), equalTo("LICENSE.txt")); + assertThat(assets.get(0).getSize(), equalTo(1104L)); + assertThat(assets.get(0).getContentType(), equalTo("application/text")); + assertThat(assets.get(0).getState(), equalTo("uploaded")); + assertThat(assets.get(0).getDownloadCount(), equalTo(0L)); + assertThat(assets.get(0).getOwner(), sameInstance(release.getOwner())); + assertThat(assets.get(0).getBrowserDownloadUrl(), + containsString("/temp-testCreateRepository/releases/download/release_tag/LICENSE.txt")); + + return asset; } private GHRelease createRelease(GHRepository repository) throws IOException { @@ -101,32 +119,14 @@ private void delete(File toDelete) { toDelete.delete(); } - private void deleteAsset(GHRelease release, GHAsset asset) throws IOException { - asset.delete(); - assertThat(release.listAssets().toList(), is(empty())); - } - - private void updateAsset(GHRelease release, GHAsset asset) throws IOException { - asset.setLabel("test label"); - assertThat(release.listAssets().toList().get(0).getLabel(), equalTo("test label")); - } - - private GHAsset uploadAsset(GHRelease release) throws IOException { - GHAsset asset = release.uploadAsset(new File("LICENSE.txt"), "application/text"); - assertThat(asset, notNullValue()); - List cachedAssets = release.getAssets(); - assertThat(cachedAssets, is(empty())); - List assets = release.listAssets().toList(); - assertThat(assets.size(), equalTo(1)); - assertThat(assets.get(0).getName(), equalTo("LICENSE.txt")); - assertThat(assets.get(0).getSize(), equalTo(1104L)); - assertThat(assets.get(0).getContentType(), equalTo("application/text")); - assertThat(assets.get(0).getState(), equalTo("uploaded")); - assertThat(assets.get(0).getDownloadCount(), equalTo(0L)); - assertThat(assets.get(0).getOwner(), sameInstance(release.getOwner())); - assertThat(assets.get(0).getBrowserDownloadUrl(), - containsString("/temp-testCreateRepository/releases/download/release_tag/LICENSE.txt")); - - return asset; + private File createDummyFile(File repoDir) throws IOException { + File file = new File(repoDir, "testFile-" + System.currentTimeMillis()); + PrintWriter writer = new PrintWriter(new FileWriter(file)); + try { + writer.println("test file"); + } finally { + writer.close(); + } + return file; } } diff --git a/src/test/java/org/kohsuke/github/PayloadRule.java b/src/test/java/org/kohsuke/github/PayloadRule.java index 3afe64d072..dcd41cae0f 100644 --- a/src/test/java/org/kohsuke/github/PayloadRule.java +++ b/src/test/java/org/kohsuke/github/PayloadRule.java @@ -24,11 +24,11 @@ */ public class PayloadRule implements TestRule { - private String resourceName; + private final String type; private Class testClass; - private final String type; + private String resourceName; /** * Instantiates a new payload rule. @@ -65,6 +65,24 @@ public void evaluate() throws Throwable { }; } + /** + * As input stream. + * + * @return the input stream + * @throws FileNotFoundException + * the file not found exception + */ + public InputStream asInputStream() throws FileNotFoundException { + String name = resourceName.startsWith("/") + ? resourceName + type + : testClass.getSimpleName() + "/" + resourceName + type; + InputStream stream = testClass.getResourceAsStream(name); + if (stream == null) { + throw new FileNotFoundException(String.format("Resource %s from class %s", name, testClass)); + } + return stream; + } + /** * As bytes. * @@ -82,45 +100,51 @@ public byte[] asBytes() throws IOException { } /** - * As input stream. + * As string. * - * @return the input stream - * @throws FileNotFoundException - * the file not found exception + * @param encoding + * the encoding + * @return the string + * @throws IOException + * Signals that an I/O exception has occurred. */ - public InputStream asInputStream() throws FileNotFoundException { - String name = resourceName.startsWith("/") - ? resourceName + type - : testClass.getSimpleName() + "/" + resourceName + type; - InputStream stream = testClass.getResourceAsStream(name); - if (stream == null) { - throw new FileNotFoundException(String.format("Resource %s from class %s", name, testClass)); - } - return stream; + public String asString(Charset encoding) throws IOException { + return new String(asBytes(), encoding.name()); } /** - * As reader. + * As string. * - * @return the reader - * @throws FileNotFoundException - * the file not found exception + * @param encoding + * the encoding + * @return the string + * @throws IOException + * Signals that an I/O exception has occurred. */ - public Reader asReader() throws FileNotFoundException { - return new InputStreamReader(asInputStream(), Charset.defaultCharset()); + public String asString(String encoding) throws IOException { + return new String(asBytes(), encoding); + } + + /** + * As string. + * + * @return the string + * @throws IOException + * Signals that an I/O exception has occurred. + */ + public String asString() throws IOException { + return new String(asBytes(), Charset.defaultCharset().name()); } /** * As reader. * - * @param encoding - * the encoding * @return the reader * @throws FileNotFoundException * the file not found exception */ - public Reader asReader(Charset encoding) throws FileNotFoundException { - return new InputStreamReader(asInputStream(), encoding); + public Reader asReader() throws FileNotFoundException { + return new InputStreamReader(asInputStream(), Charset.defaultCharset()); } /** @@ -151,39 +175,15 @@ public Reader asReader(String encoding) throws IOException { } /** - * As string. - * - * @return the string - * @throws IOException - * Signals that an I/O exception has occurred. - */ - public String asString() throws IOException { - return new String(asBytes(), Charset.defaultCharset().name()); - } - - /** - * As string. - * - * @param encoding - * the encoding - * @return the string - * @throws IOException - * Signals that an I/O exception has occurred. - */ - public String asString(Charset encoding) throws IOException { - return new String(asBytes(), encoding.name()); - } - - /** - * As string. + * As reader. * * @param encoding * the encoding - * @return the string - * @throws IOException - * Signals that an I/O exception has occurred. + * @return the reader + * @throws FileNotFoundException + * the file not found exception */ - public String asString(String encoding) throws IOException { - return new String(asBytes(), encoding); + public Reader asReader(Charset encoding) throws FileNotFoundException { + return new InputStreamReader(asInputStream(), encoding); } } diff --git a/src/test/java/org/kohsuke/github/RateLimitCheckerTest.java b/src/test/java/org/kohsuke/github/RateLimitCheckerTest.java index 12ce65b2f7..8192ce0359 100644 --- a/src/test/java/org/kohsuke/github/RateLimitCheckerTest.java +++ b/src/test/java/org/kohsuke/github/RateLimitCheckerTest.java @@ -17,16 +17,12 @@ */ public class RateLimitCheckerTest extends AbstractGitHubWireMockTest { - private static GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); - } + /** The rate limit. */ + GHRateLimit rateLimit = null; /** The previous limit. */ GHRateLimit previousLimit = null; - /** The rate limit. */ - GHRateLimit rateLimit = null; - /** * Instantiates a new rate limit checker test. */ @@ -34,6 +30,16 @@ public RateLimitCheckerTest() { useDefaultGitHub = false; } + /** + * Gets the wire mock options. + * + * @return the wire mock options + */ + @Override + protected WireMockConfiguration getWireMockOptions() { + return super.getWireMockOptions().extensions(templating.newResponseTransformer()); + } + /** * Test git hub rate limit. * @@ -51,7 +57,6 @@ public void testGitHubRateLimit() throws Exception { // Give this a moment Thread.sleep(1000); - // noinspection UseOfObsoleteDateTimeApi templating.testStartDate = new Date(); // ------------------------------------------------------------- // /user gets response with rate limit information @@ -97,16 +102,6 @@ public void testGitHubRateLimit() throws Exception { assertThat(rateLimit.getCore().getRemaining(), equalTo(4601)); } - /** - * Gets the wire mock options. - * - * @return the wire mock options - */ - @Override - protected WireMockConfiguration getWireMockOptions() { - return super.getWireMockOptions().extensions(templating.newResponseTransformer()); - } - /** * Update test rate limit. */ @@ -115,4 +110,8 @@ protected void updateTestRateLimit() { rateLimit = gitHub.lastRateLimit(); } + private static GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } + } diff --git a/src/test/java/org/kohsuke/github/RateLimitHandlerTest.java b/src/test/java/org/kohsuke/github/RateLimitHandlerTest.java index 8781b544ee..5e326cbba3 100644 --- a/src/test/java/org/kohsuke/github/RateLimitHandlerTest.java +++ b/src/test/java/org/kohsuke/github/RateLimitHandlerTest.java @@ -42,6 +42,16 @@ public RateLimitHandlerTest() { useDefaultGitHub = false; } + /** + * Gets the wire mock options. + * + * @return the wire mock options + */ + @Override + protected WireMockConfiguration getWireMockOptions() { + return super.getWireMockOptions().extensions(templating.newResponseTransformer()); + } + /** * Test handler fail. * @@ -137,20 +147,25 @@ public void onError(@NotNull GitHubConnectorResponse connectorResponse) throws I } /** - * Test handler wait stuck. + * Test the wait logic in the case where the "Date" header field is missing from the response. * - * @throws Exception - * the exception + * @throws IOException + * if the code under test throws that exception */ @Test - public void testHandler_WaitStuck() throws Exception { + public void testHandler_Wait_Missing_Date_Header() throws IOException { // Customized response that templates the date to keep things working snapshotNotAllowed(); gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) .withRateLimitHandler(new GitHubRateLimitHandler() { + @Override - public void onError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException { + public void onError(@NotNull GitHubConnectorResponse connectorResponse) throws IOException { + long waitTime = GitHubRateLimitHandler.WAIT.parseWaitTime(connectorResponse); + assertThat(waitTime, equalTo(3 * 1000l)); + + GitHubAbuseLimitHandler.WAIT.onError(connectorResponse); } }) .build(); @@ -158,36 +173,25 @@ public void onError(@Nonnull GitHubConnectorResponse connectorResponse) throws I gitHub.getMyself(); assertThat(mockGitHub.getRequestCount(), equalTo(1)); - try { - getTempRepository(); - fail(); - } catch (Exception e) { - assertThat(e, instanceOf(GHIOException.class)); - } - - assertThat(mockGitHub.getRequestCount(), equalTo(4)); + getTempRepository(); + assertThat(mockGitHub.getRequestCount(), equalTo(3)); } /** - * Test the wait logic in the case where the "Date" header field is missing from the response. + * Test handler wait stuck. * - * @throws IOException - * if the code under test throws that exception + * @throws Exception + * the exception */ @Test - public void testHandler_Wait_Missing_Date_Header() throws IOException { + public void testHandler_WaitStuck() throws Exception { // Customized response that templates the date to keep things working snapshotNotAllowed(); gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) .withRateLimitHandler(new GitHubRateLimitHandler() { - @Override - public void onError(@NotNull GitHubConnectorResponse connectorResponse) throws IOException { - long waitTime = GitHubRateLimitHandler.WAIT.parseWaitTime(connectorResponse); - assertThat(waitTime, equalTo(3 * 1000l)); - - GitHubAbuseLimitHandler.WAIT.onError(connectorResponse); + public void onError(@Nonnull GitHubConnectorResponse connectorResponse) throws IOException { } }) .build(); @@ -195,18 +199,14 @@ public void onError(@NotNull GitHubConnectorResponse connectorResponse) throws I gitHub.getMyself(); assertThat(mockGitHub.getRequestCount(), equalTo(1)); - getTempRepository(); - assertThat(mockGitHub.getRequestCount(), equalTo(3)); - } + try { + getTempRepository(); + fail(); + } catch (Exception e) { + assertThat(e, instanceOf(GHIOException.class)); + } - /** - * Gets the wire mock options. - * - * @return the wire mock options - */ - @Override - protected WireMockConfiguration getWireMockOptions() { - return super.getWireMockOptions().extensions(templating.newResponseTransformer()); + assertThat(mockGitHub.getRequestCount(), equalTo(4)); } } diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java index 16513ca57c..2fd49958b6 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java @@ -9,24 +9,78 @@ import java.util.Iterator; import java.util.List; -import static org.hamcrest.CoreMatchers.equalTo; - // TODO: Auto-generated Javadoc /** * The Class RepositoryTrafficTest. */ public class RepositoryTrafficTest extends AbstractGitHubWireMockTest { - private static GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j").getRepository("github-api"); + /** + * Create default RepositoryTrafficTest instance + */ + public RepositoryTrafficTest() { } final private String repositoryName = "github-api"; + @SuppressWarnings("unchecked") + private void checkResponse(T expected, T actual) { + assertThat(actual.getCount(), Matchers.equalTo(expected.getCount())); + assertThat(actual.getUniques(), Matchers.equalTo(expected.getUniques())); + + List expectedList = expected.getDailyInfo(); + List actualList = actual.getDailyInfo(); + Iterator expectedIt; + Iterator actualIt; + + assertThat(actualList.size(), Matchers.equalTo(expectedList.size())); + expectedIt = expectedList.iterator(); + actualIt = actualList.iterator(); + + while (expectedIt.hasNext() && actualIt.hasNext()) { + DailyInfo expectedDailyInfo = expectedIt.next(); + DailyInfo actualDailyInfo = actualIt.next(); + assertThat(actualDailyInfo.getCount(), Matchers.equalTo(expectedDailyInfo.getCount())); + assertThat(actualDailyInfo.getUniques(), Matchers.equalTo(expectedDailyInfo.getUniques())); + assertThat(actualDailyInfo.getTimestamp(), Matchers.equalTo(expectedDailyInfo.getTimestamp())); + } + } + + private static GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j").getRepository("github-api"); + } + /** - * Create default RepositoryTrafficTest instance + * Test get views. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ - public RepositoryTrafficTest() { + @Test + public void testGetViews() throws IOException { + // Would change all the time + snapshotNotAllowed(); + + GHRepository repository = getRepository(gitHub); + GHRepositoryViewTraffic views = repository.getViewTraffic(); + + GHRepositoryViewTraffic expectedResult = new GHRepositoryViewTraffic(3533, + 616, + Arrays.asList(new GHRepositoryViewTraffic.DailyInfo("2020-02-08T00:00:00Z", 101, 31), + new GHRepositoryViewTraffic.DailyInfo("2020-02-09T00:00:00Z", 92, 22), + new GHRepositoryViewTraffic.DailyInfo("2020-02-10T00:00:00Z", 317, 84), + new GHRepositoryViewTraffic.DailyInfo("2020-02-11T00:00:00Z", 365, 90), + new GHRepositoryViewTraffic.DailyInfo("2020-02-12T00:00:00Z", 428, 78), + new GHRepositoryViewTraffic.DailyInfo("2020-02-13T00:00:00Z", 334, 52), + new GHRepositoryViewTraffic.DailyInfo("2020-02-14T00:00:00Z", 138, 44), + new GHRepositoryViewTraffic.DailyInfo("2020-02-15T00:00:00Z", 76, 13), + new GHRepositoryViewTraffic.DailyInfo("2020-02-16T00:00:00Z", 99, 27), + new GHRepositoryViewTraffic.DailyInfo("2020-02-17T00:00:00Z", 367, 65), + new GHRepositoryViewTraffic.DailyInfo("2020-02-18T00:00:00Z", 411, 76), + new GHRepositoryViewTraffic.DailyInfo("2020-02-19T00:00:00Z", 140, 61), + new GHRepositoryViewTraffic.DailyInfo("2020-02-20T00:00:00Z", 259, 55), + new GHRepositoryViewTraffic.DailyInfo("2020-02-21T00:00:00Z", 406, 66))); + checkResponse(expectedResult, views); } /** @@ -41,8 +95,6 @@ public void testGetClones() throws IOException { snapshotNotAllowed(); GHRepository repository = getRepository(gitHub); - assertThat(repository.getPushedAt(), equalTo(GitHubClient.parseInstant("2020-02-21T21:17:31Z"))); - GHRepositoryCloneTraffic clones = repository.getCloneTraffic(); GHRepositoryCloneTraffic expectedResult = new GHRepositoryCloneTraffic(128, @@ -86,60 +138,4 @@ public void testGetTrafficStatsAccessFailureDueToInsufficientPermissions() throw } catch (HttpException ex) { } } - - /** - * Test get views. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testGetViews() throws IOException { - // Would change all the time - snapshotNotAllowed(); - - GHRepository repository = getRepository(gitHub); - GHRepositoryViewTraffic views = repository.getViewTraffic(); - - GHRepositoryViewTraffic expectedResult = new GHRepositoryViewTraffic(3533, - 616, - Arrays.asList(new GHRepositoryViewTraffic.DailyInfo("2020-02-08T00:00:00Z", 101, 31), - new GHRepositoryViewTraffic.DailyInfo("2020-02-09T00:00:00Z", 92, 22), - new GHRepositoryViewTraffic.DailyInfo("2020-02-10T00:00:00Z", 317, 84), - new GHRepositoryViewTraffic.DailyInfo("2020-02-11T00:00:00Z", 365, 90), - new GHRepositoryViewTraffic.DailyInfo("2020-02-12T00:00:00Z", 428, 78), - new GHRepositoryViewTraffic.DailyInfo("2020-02-13T00:00:00Z", 334, 52), - new GHRepositoryViewTraffic.DailyInfo("2020-02-14T00:00:00Z", 138, 44), - new GHRepositoryViewTraffic.DailyInfo("2020-02-15T00:00:00Z", 76, 13), - new GHRepositoryViewTraffic.DailyInfo("2020-02-16T00:00:00Z", 99, 27), - new GHRepositoryViewTraffic.DailyInfo("2020-02-17T00:00:00Z", 367, 65), - new GHRepositoryViewTraffic.DailyInfo("2020-02-18T00:00:00Z", 411, 76), - new GHRepositoryViewTraffic.DailyInfo("2020-02-19T00:00:00Z", 140, 61), - new GHRepositoryViewTraffic.DailyInfo("2020-02-20T00:00:00Z", 259, 55), - new GHRepositoryViewTraffic.DailyInfo("2020-02-21T00:00:00Z", 406, 66))); - checkResponse(expectedResult, views); - } - - @SuppressWarnings("unchecked") - private void checkResponse(T expected, T actual) { - assertThat(actual.getCount(), Matchers.equalTo(expected.getCount())); - assertThat(actual.getUniques(), Matchers.equalTo(expected.getUniques())); - - List expectedList = expected.getDailyInfo(); - List actualList = actual.getDailyInfo(); - Iterator expectedIt; - Iterator actualIt; - - assertThat(actualList.size(), Matchers.equalTo(expectedList.size())); - expectedIt = expectedList.iterator(); - actualIt = actualList.iterator(); - - while (expectedIt.hasNext() && actualIt.hasNext()) { - DailyInfo expectedDailyInfo = expectedIt.next(); - DailyInfo actualDailyInfo = actualIt.next(); - assertThat(actualDailyInfo.getCount(), Matchers.equalTo(expectedDailyInfo.getCount())); - assertThat(actualDailyInfo.getUniques(), Matchers.equalTo(expectedDailyInfo.getUniques())); - assertThat(actualDailyInfo.getTimestamp(), Matchers.equalTo(expectedDailyInfo.getTimestamp())); - } - } } diff --git a/src/test/java/org/kohsuke/github/RequesterRetryTest.java b/src/test/java/org/kohsuke/github/RequesterRetryTest.java index 5d6865a869..5675036a29 100644 --- a/src/test/java/org/kohsuke/github/RequesterRetryTest.java +++ b/src/test/java/org/kohsuke/github/RequesterRetryTest.java @@ -3,17 +3,18 @@ import okhttp3.ConnectionPool; import okhttp3.OkHttpClient; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.kohsuke.github.connector.GitHubConnector; import org.kohsuke.github.connector.GitHubConnectorRequest; import org.kohsuke.github.connector.GitHubConnectorResponse; -import org.kohsuke.github.connector.GitHubConnectorResponseTest; import org.kohsuke.github.extras.HttpClientGitHubConnector; import org.kohsuke.github.extras.okhttp3.OkHttpGitHubConnector; import java.io.*; +import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -35,163 +36,14 @@ */ public class RequesterRetryTest extends AbstractGitHubWireMockTest { - /** - * The Interface Thrower. - * - * @param - * the element type - */ - @FunctionalInterface - public interface Thrower { - - /** - * Throw error. - * - * @throws E - * the e - */ - void throwError() throws E; - } - private static class GitHubConnectorResponseWrapper extends GitHubConnectorResponse { - - private final GitHubConnectorResponse wrapped; - - GitHubConnectorResponseWrapper(GitHubConnectorResponse response) { - super(GitHubConnectorResponseTest.EMPTY_REQUEST, -1, new HashMap<>()); - wrapped = response; - } - - @Nonnull - @Override - public Map> allHeaders() { - return wrapped.allHeaders(); - } - - @NotNull @Override - public InputStream bodyStream() throws IOException { - return wrapped.bodyStream(); - } - - @Override - public void close() throws IOException { - wrapped.close(); - } - - @CheckForNull - @Override - public String header(String name) { - return wrapped.header(name); - } - - @Nonnull - @Override - public GitHubConnectorRequest request() { - return wrapped.request(); - } - - @Override - public int statusCode() { - return wrapped.statusCode(); - } - - @Override - protected InputStream rawBodyStream() throws IOException { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'rawBodyStream'"); - } - } - /** - * The Class InputStreamThrowingHttpConnector. - * - * @param - * the element type - */ - static class BodyStreamThrowingGitHubConnector extends HttpClientGitHubConnector { - - private final Thrower thrower; - - final int[] count = { 0 }; - - /** - * Instantiates a new input stream throwing http connector. - * - * @param thrower - * the thrower - */ - BodyStreamThrowingGitHubConnector(final Thrower thrower) { - super(); - this.thrower = thrower; - } - - @Override - public GitHubConnectorResponse send(GitHubConnectorRequest connectorRequest) throws IOException { - if (connectorRequest.url().toString().contains(GITHUB_API_TEST_ORG)) { - count[0]++; - } - GitHubConnectorResponse response = super.send(connectorRequest); - return new GitHubConnectorResponseWrapper(response) { - @NotNull @Override - public InputStream bodyStream() throws IOException { - if (response.request().url().toString().contains(GITHUB_API_TEST_ORG)) { - if (count[0] % 3 != 0) { - thrower.throwError(); - } - } - return super.bodyStream(); - } - }; - } - } + private static Logger log = Logger.getLogger(GitHubClient.class.getName()); // matches the logger in the affected + // class + private static OutputStream logCapturingStream; + private static StreamHandler customLogHandler; /** The connection. */ // HttpURLConnection connection; - /** - * The Class ResponseCodeThrowingGitHubConnector. - * - * @param - * the element type - */ - static class SendThrowingGitHubConnector extends HttpClientGitHubConnector { - - private final Thrower thrower; - - final int[] count = { 0 }; - - /** - * Instantiates a new response code throwing http connector. - * - * @param thrower - * the thrower - */ - SendThrowingGitHubConnector(final Thrower thrower) { - super(); - this.thrower = thrower; - } - - @Override - public GitHubConnectorResponse send(GitHubConnectorRequest connectorRequest) throws IOException { - if (connectorRequest.url().toString().contains(GITHUB_API_TEST_ORG)) { - count[0]++; - // throwing before we call super.send() simulates error - if (count[0] % 3 != 0) { - thrower.throwError(); - } - } - - GitHubConnectorResponse response = super.send(connectorRequest); - return new GitHubConnectorResponseWrapper(response); - } - - } - - private static StreamHandler customLogHandler; - - private static Logger log = Logger.getLogger(GitHubClient.class.getName()); // matches the logger in the affected - - // class - private static OutputStream logCapturingStream; - /** The base request count. */ int baseRequestCount; @@ -202,6 +54,21 @@ public RequesterRetryTest() { useDefaultGitHub = false; } + /** + * Gets the repository. + * + * @return the repository + * @throws IOException + * Signals that an I/O exception has occurred. + */ + protected GHRepository getRepository() throws IOException { + return getRepository(gitHub); + } + + private GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + } + /** * Attach log capturer. */ @@ -217,12 +84,61 @@ public void attachLogCapturer() { * Gets the test captured log. * * @return the test captured log + * @throws IOException + * Signals that an I/O exception has occurred. */ - public String getTestCapturedLog() { + public String getTestCapturedLog() throws IOException { customLogHandler.flush(); return logCapturingStream.toString(); } + /** + * Reset test captured log. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + public void resetTestCapturedLog() throws IOException { + Logger.getLogger(GitHubClient.class.getName()).removeHandler(customLogHandler); + Logger.getLogger(OkHttpClient.class.getName()).removeHandler(customLogHandler); + customLogHandler.close(); + attachLogCapturer(); + } + + /** + * Test git hub is api url valid. + * + * @throws Exception + * the exception + */ + @Ignore("Used okhttp3 and this to verify connection closing. Too flaky for CI system.") + @Test + public void testGitHubIsApiUrlValid() throws Exception { + + OkHttpClient client = new OkHttpClient().newBuilder() + .connectionPool(new ConnectionPool(2, 100, TimeUnit.MILLISECONDS)) + .build(); + + OkHttpGitHubConnector connector = new OkHttpGitHubConnector(client); + + for (int x = 0; x < 100; x++) { + + this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) + .withConnector(connector) + .build(); + + try { + gitHub.checkApiUrlValidity(); + } catch (IOException ioe) { + assertThat(ioe.getMessage(), containsString("private mode enabled")); + } + Thread.sleep(100); + } + + String capturedLog = getTestCapturedLog(); + assertThat(capturedLog, not(containsString("leaked"))); + } + // /** // * Test socket connection and retry. // * @@ -298,87 +214,74 @@ public String getTestCapturedLog() { // } /** - * Reset test captured log. - */ - public void resetTestCapturedLog() { - Logger.getLogger(GitHubClient.class.getName()).removeHandler(customLogHandler); - Logger.getLogger(OkHttpClient.class.getName()).removeHandler(customLogHandler); - customLogHandler.close(); - attachLogCapturer(); - } - - /** - * Test git hub is api url valid. + * Test socket connection and retry success. * * @throws Exception * the exception */ - @Ignore("Used okhttp3 and this to verify connection closing. Too flaky for CI system.") - @Test - public void testGitHubIsApiUrlValid() throws Exception { - - OkHttpClient client = new OkHttpClient().newBuilder() - .connectionPool(new ConnectionPool(2, 100, TimeUnit.MILLISECONDS)) - .build(); - - OkHttpGitHubConnector connector = new OkHttpGitHubConnector(client); - - for (int x = 0; x < 100; x++) { - - this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) - .withConnector(connector) - .build(); - - try { - gitHub.checkApiUrlValidity(); - } catch (IOException ioe) { - assertThat(ioe.getMessage(), containsString("private mode enabled")); - } - Thread.sleep(100); - } - - String capturedLog = getTestCapturedLog(); - assertThat(capturedLog, not(containsString("leaked"))); - } + // @Test + // public void testSocketConnectionAndRetry_Success() throws Exception { + // // Only implemented for HttpURLConnection connectors + // Assume.assumeThat(DefaultGitHubConnector.create(), not(instanceOf(HttpClientGitHubConnector.class))); - /** - * Test response code connection exceptions. - * - * @throws Exception - * the exception - */ - // @Test - // public void testResponseCodeConnectionExceptions() throws Exception { - // // Because the test throws at the very start of send(), there is only one connection for 3 retries - // GitHubConnector connector = new SendThrowingGitHubConnector<>(() -> { - // throw new SocketException(); - // }); - // runConnectionExceptionTest(connector, 1); - // runConnectionExceptionStatusCodeTest(connector, 1); + // // CONNECTION_RESET_BY_PEER errors result in two requests each + // // to get this failure for "3" tries we have to do 6 queries. + // // If there are only 5 errors we succeed. + // this.mockGitHub.apiServer() + // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) + // .inScenario("Retry") + // .whenScenarioStateIs(Scenario.STARTED) + // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) + // .setNewScenarioState("Retry-1"); + // this.mockGitHub.apiServer() + // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) + // .inScenario("Retry") + // .whenScenarioStateIs("Retry-1") + // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) + // .setNewScenarioState("Retry-2"); + // this.mockGitHub.apiServer() + // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) + // .inScenario("Retry") + // .whenScenarioStateIs("Retry-2") + // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) + // .setNewScenarioState("Retry-3"); + // this.mockGitHub.apiServer() + // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) + // .inScenario("Retry") + // .whenScenarioStateIs("Retry-3") + // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) + // .setNewScenarioState("Retry-4"); + // this.mockGitHub.apiServer() + // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) + // .atPriority(0) + // .inScenario("Retry") + // .whenScenarioStateIs("Retry-4") + // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) + // .setNewScenarioState("Retry-5"); - // connector = new SendThrowingGitHubConnector<>(() -> { - // throw new SocketTimeoutException(); - // }); - // runConnectionExceptionTest(connector, 1); - // runConnectionExceptionStatusCodeTest(connector, 1); + // this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); - // connector = new SendThrowingGitHubConnector<>(() -> { - // throw new SSLHandshakeException("TestFailure"); - // }); - // runConnectionExceptionTest(connector, 1); - // runConnectionExceptionStatusCodeTest(connector, 1); + // GHRepository repo = getRepository(); + // baseRequestCount = this.mockGitHub.getRequestCount(); + // GHBranch branch = repo.getBranch("test/timeout"); + // assertThat(branch, notNullValue()); + // String capturedLog = getTestCapturedLog(); + // assertThat(capturedLog, containsString("(2 retries remaining)")); + // assertThat(capturedLog, containsString("(1 retries remaining)")); + + // assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 6)); // } /** - * Test input stream failure exceptions. + * Test response code failure exceptions. * * @throws Exception * the exception */ @Test - public void testInputStreamFailureExceptions() throws Exception { + public void testResponseCodeFailureExceptions() throws Exception { // No retry for these Exceptions - GitHubConnector connector = new BodyStreamThrowingGitHubConnector<>(() -> { + GitHubConnector connector = new SendThrowingGitHubConnector<>(() -> { throw new IOException("Custom"); }); this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) @@ -396,51 +299,40 @@ public void testInputStreamFailureExceptions() throws Exception { assertThat(e.getCause().getMessage(), is("Custom")); String capturedLog = getTestCapturedLog(); assertThat(capturedLog, not(containsString("retries remaining"))); - assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 1)); + assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount)); } - // FileNotFound doesn't need a special connector - this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); + connector = new SendThrowingGitHubConnector<>(() -> { + throw new FileNotFoundException("Custom"); + }); + this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) + .withConnector(connector) + .build(); resetTestCapturedLog(); baseRequestCount = this.mockGitHub.getRequestCount(); try { - this.gitHub.getOrganization(GITHUB_API_TEST_ORG + "-missing"); + this.gitHub.getOrganization(GITHUB_API_TEST_ORG); fail(); } catch (Exception e) { - assertThat(e, instanceOf(GHFileNotFoundException.class)); - assertThat(e.getCause(), instanceOf(FileNotFoundException.class)); - assertThat(e.getCause().getMessage(), containsString("hub4j-test-org-missing")); + assertThat(e, instanceOf(FileNotFoundException.class)); + assertThat(e.getMessage(), is("Custom")); String capturedLog = getTestCapturedLog(); assertThat(capturedLog, not(containsString("retries remaining"))); - assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 1)); + assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount)); } - - // FileNotFound doesn't need a special connector - this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); - - resetTestCapturedLog(); - baseRequestCount = this.mockGitHub.getRequestCount(); - assertThat( - this.gitHub.createRequest() - .withUrlPath("/orgs/" + GITHUB_API_TEST_ORG + "-missing") - .fetchHttpStatusCode(), - equalTo(404)); - String capturedLog = getTestCapturedLog(); - assertThat(capturedLog, not(containsString("retries remaining"))); - assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 1)); } /** - * Test response code failure exceptions. + * Test input stream failure exceptions. * * @throws Exception * the exception */ @Test - public void testResponseCodeFailureExceptions() throws Exception { + public void testInputStreamFailureExceptions() throws Exception { // No retry for these Exceptions - GitHubConnector connector = new SendThrowingGitHubConnector<>(() -> { + GitHubConnector connector = new BodyStreamThrowingGitHubConnector<>(() -> { throw new IOException("Custom"); }); this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) @@ -458,116 +350,69 @@ public void testResponseCodeFailureExceptions() throws Exception { assertThat(e.getCause().getMessage(), is("Custom")); String capturedLog = getTestCapturedLog(); assertThat(capturedLog, not(containsString("retries remaining"))); - assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount)); + assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 1)); } - connector = new SendThrowingGitHubConnector<>(() -> { - throw new FileNotFoundException("Custom"); - }); - this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) - .withConnector(connector) - .build(); + // FileNotFound doesn't need a special connector + this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); resetTestCapturedLog(); baseRequestCount = this.mockGitHub.getRequestCount(); try { - this.gitHub.getOrganization(GITHUB_API_TEST_ORG); + this.gitHub.getOrganization(GITHUB_API_TEST_ORG + "-missing"); fail(); } catch (Exception e) { - assertThat(e, instanceOf(FileNotFoundException.class)); - assertThat(e.getMessage(), is("Custom")); + assertThat(e, instanceOf(GHFileNotFoundException.class)); + assertThat(e.getCause(), instanceOf(FileNotFoundException.class)); + assertThat(e.getCause().getMessage(), containsString("hub4j-test-org-missing")); String capturedLog = getTestCapturedLog(); assertThat(capturedLog, not(containsString("retries remaining"))); - assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount)); + assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 1)); } + + // FileNotFound doesn't need a special connector + this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); + + resetTestCapturedLog(); + baseRequestCount = this.mockGitHub.getRequestCount(); + assertThat( + this.gitHub.createRequest() + .withUrlPath("/orgs/" + GITHUB_API_TEST_ORG + "-missing") + .fetchHttpStatusCode(), + equalTo(404)); + String capturedLog = getTestCapturedLog(); + assertThat(capturedLog, not(containsString("retries remaining"))); + assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 1)); } /** - * Test socket connection and retry success. + * Test response code connection exceptions. * * @throws Exception * the exception */ // @Test - // public void testSocketConnectionAndRetry_Success() throws Exception { - // // Only implemented for HttpURLConnection connectors - // Assume.assumeThat(DefaultGitHubConnector.create(), not(instanceOf(HttpClientGitHubConnector.class))); - - // // CONNECTION_RESET_BY_PEER errors result in two requests each - // // to get this failure for "3" tries we have to do 6 queries. - // // If there are only 5 errors we succeed. - // this.mockGitHub.apiServer() - // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) - // .inScenario("Retry") - // .whenScenarioStateIs(Scenario.STARTED) - // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) - // .setNewScenarioState("Retry-1"); - // this.mockGitHub.apiServer() - // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) - // .inScenario("Retry") - // .whenScenarioStateIs("Retry-1") - // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) - // .setNewScenarioState("Retry-2"); - // this.mockGitHub.apiServer() - // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) - // .inScenario("Retry") - // .whenScenarioStateIs("Retry-2") - // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) - // .setNewScenarioState("Retry-3"); - // this.mockGitHub.apiServer() - // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) - // .inScenario("Retry") - // .whenScenarioStateIs("Retry-3") - // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) - // .setNewScenarioState("Retry-4"); - // this.mockGitHub.apiServer() - // .stubFor(get(urlMatching(".+/branches/test/timeout")).atPriority(0) - // .atPriority(0) - // .inScenario("Retry") - // .whenScenarioStateIs("Retry-4") - // .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))) - // .setNewScenarioState("Retry-5"); - - // this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()).build(); + // public void testResponseCodeConnectionExceptions() throws Exception { + // // Because the test throws at the very start of send(), there is only one connection for 3 retries + // GitHubConnector connector = new SendThrowingGitHubConnector<>(() -> { + // throw new SocketException(); + // }); + // runConnectionExceptionTest(connector, 1); + // runConnectionExceptionStatusCodeTest(connector, 1); - // GHRepository repo = getRepository(); - // baseRequestCount = this.mockGitHub.getRequestCount(); - // GHBranch branch = repo.getBranch("test/timeout"); - // assertThat(branch, notNullValue()); - // String capturedLog = getTestCapturedLog(); - // assertThat(capturedLog, containsString("(2 retries remaining)")); - // assertThat(capturedLog, containsString("(1 retries remaining)")); + // connector = new SendThrowingGitHubConnector<>(() -> { + // throw new SocketTimeoutException(); + // }); + // runConnectionExceptionTest(connector, 1); + // runConnectionExceptionStatusCodeTest(connector, 1); - // assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 6)); + // connector = new SendThrowingGitHubConnector<>(() -> { + // throw new SSLHandshakeException("TestFailure"); + // }); + // runConnectionExceptionTest(connector, 1); + // runConnectionExceptionStatusCodeTest(connector, 1); // } - private GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); - } - - private void runConnectionExceptionStatusCodeTest(GitHubConnector connector, int expectedRequestCount) - throws IOException { - // now wire in the connector - this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) - .withConnector(connector) - .build(); - - resetTestCapturedLog(); - baseRequestCount = this.mockGitHub.getRequestCount(); - assertThat(this.gitHub.createRequest().withUrlPath("/orgs/" + GITHUB_API_TEST_ORG).fetchHttpStatusCode(), - equalTo(200)); - String capturedLog = getTestCapturedLog(); - if (expectedRequestCount > 0) { - assertThat(capturedLog, containsString("(2 retries remaining)")); - assertThat(capturedLog, containsString("(1 retries remaining)")); - assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + expectedRequestCount)); - } else { - // Success without retries - assertThat(capturedLog, not(containsString("retries remaining"))); - assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 1)); - } - } - /** * Test input stream connection exceptions. * @@ -620,14 +465,214 @@ private void runConnectionExceptionTest(GitHubConnector connector, int expectedR assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + expectedRequestCount)); } + private void runConnectionExceptionStatusCodeTest(GitHubConnector connector, int expectedRequestCount) + throws IOException { + // now wire in the connector + this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) + .withConnector(connector) + .build(); + + resetTestCapturedLog(); + baseRequestCount = this.mockGitHub.getRequestCount(); + assertThat(this.gitHub.createRequest().withUrlPath("/orgs/" + GITHUB_API_TEST_ORG).fetchHttpStatusCode(), + equalTo(200)); + String capturedLog = getTestCapturedLog(); + if (expectedRequestCount > 0) { + assertThat(capturedLog, containsString("(2 retries remaining)")); + assertThat(capturedLog, containsString("(1 retries remaining)")); + assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + expectedRequestCount)); + } else { + // Success without retries + assertThat(capturedLog, not(containsString("retries remaining"))); + assertThat(this.mockGitHub.getRequestCount(), equalTo(baseRequestCount + 1)); + } + } + /** - * Gets the repository. + * The Class ResponseCodeThrowingGitHubConnector. * - * @return the repository - * @throws IOException - * Signals that an I/O exception has occurred. + * @param + * the element type */ - protected GHRepository getRepository() throws IOException { - return getRepository(gitHub); + static class SendThrowingGitHubConnector extends HttpClientGitHubConnector { + + final int[] count = { 0 }; + + private final Thrower thrower; + + /** + * Instantiates a new response code throwing http connector. + * + * @param thrower + * the thrower + */ + SendThrowingGitHubConnector(final Thrower thrower) { + super(); + this.thrower = thrower; + } + + @Override + public GitHubConnectorResponse send(GitHubConnectorRequest connectorRequest) throws IOException { + if (connectorRequest.url().toString().contains(GITHUB_API_TEST_ORG)) { + count[0]++; + // throwing before we call super.send() simulates error + if (count[0] % 3 != 0) { + thrower.throwError(); + } + } + + GitHubConnectorResponse response = super.send(connectorRequest); + return new GitHubConnectorResponseWrapper(response); + } + + } + + /** + * The Class InputStreamThrowingHttpConnector. + * + * @param + * the element type + */ + static class BodyStreamThrowingGitHubConnector extends HttpClientGitHubConnector { + + final int[] count = { 0 }; + + private final Thrower thrower; + + /** + * Instantiates a new input stream throwing http connector. + * + * @param thrower + * the thrower + */ + BodyStreamThrowingGitHubConnector(final Thrower thrower) { + super(); + this.thrower = thrower; + } + + @Override + public GitHubConnectorResponse send(GitHubConnectorRequest connectorRequest) throws IOException { + if (connectorRequest.url().toString().contains(GITHUB_API_TEST_ORG)) { + count[0]++; + } + GitHubConnectorResponse response = super.send(connectorRequest); + return new GitHubConnectorResponseWrapper(response) { + @NotNull + @Override + public InputStream bodyStream() throws IOException { + if (response.request().url().toString().contains(GITHUB_API_TEST_ORG)) { + if (count[0] % 3 != 0) { + thrower.throwError(); + } + } + return super.bodyStream(); + } + }; + } + } + + private static final GitHubConnectorRequest IGNORED_EMPTY_REQUEST = new GitHubConnectorRequest() { + @NotNull + @Override + public String method() { + return null; + } + + @NotNull + @Override + public Map> allHeaders() { + return null; + } + + @Nullable + @Override + public String header(String name) { + return null; + } + + @Nullable + @Override + public String contentType() { + return null; + } + + @Nullable + @Override + public InputStream body() { + return null; + } + + @NotNull + @Override + public URL url() { + return null; + } + + @Override + public boolean hasBody() { + return false; + } + }; + + private static class GitHubConnectorResponseWrapper extends GitHubConnectorResponse { + + private final GitHubConnectorResponse wrapped; + + GitHubConnectorResponseWrapper(GitHubConnectorResponse response) { + super(IGNORED_EMPTY_REQUEST, -1, new HashMap<>()); + wrapped = response; + } + + @CheckForNull + @Override + public String header(String name) { + return wrapped.header(name); + } + + @NotNull + @Override + public InputStream bodyStream() throws IOException { + return wrapped.bodyStream(); + } + + @Nonnull + @Override + public GitHubConnectorRequest request() { + return wrapped.request(); + } + + @Override + public int statusCode() { + return wrapped.statusCode(); + } + + @Nonnull + @Override + public Map> allHeaders() { + return wrapped.allHeaders(); + } + + @Override + public void close() throws IOException { + wrapped.close(); + } + } + + /** + * The Interface Thrower. + * + * @param + * the element type + */ + @FunctionalInterface + public interface Thrower { + + /** + * Throw error. + * + * @throws E + * the e + */ + void throwError() throws E; } } diff --git a/src/test/java/org/kohsuke/github/WireMockMultiServerRule.java b/src/test/java/org/kohsuke/github/WireMockMultiServerRule.java index 43699e51f2..0df77f446f 100644 --- a/src/test/java/org/kohsuke/github/WireMockMultiServerRule.java +++ b/src/test/java/org/kohsuke/github/WireMockMultiServerRule.java @@ -26,20 +26,22 @@ */ public class WireMockMultiServerRule implements MethodRule, TestRule { - private boolean failOnUnmatchedRequests; - private String methodName = null; - private final Options options; - /** The servers. */ protected final Map servers = new HashMap<>(); + private boolean failOnUnmatchedRequests; + private final Options options; /** - * Instantiates a new wire mock multi server rule. + * Gets the method name. + * + * @return the method name */ - public WireMockMultiServerRule() { - this(WireMockRuleConfiguration.wireMockConfig()); + public String getMethodName() { + return methodName; } + private String methodName = null; + /** * Instantiates a new wire mock multi server rule. * @@ -63,6 +65,13 @@ public WireMockMultiServerRule(Options options, boolean failOnUnmatchedRequests) this.failOnUnmatchedRequests = failOnUnmatchedRequests; } + /** + * Instantiates a new wire mock multi server rule. + */ + public WireMockMultiServerRule() { + this(WireMockRuleConfiguration.wireMockConfig()); + } + /** * Apply. * @@ -91,15 +100,6 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ return this.apply(base, method.getName()); } - /** - * Gets the method name. - * - * @return the method name - */ - public String getMethodName() { - return methodName; - } - private Statement apply(final Statement base, final String methodName) { return new Statement() { public void evaluate() throws Throwable { @@ -122,6 +122,54 @@ public void evaluate() throws Throwable { }; } + /** + * Initialize servers. + */ + protected void initializeServers() { + } + + /** + * Initialize server. + * + * @param serverId + * the server id + * @param extensions + * the extensions + */ + protected final void initializeServer(String serverId, Extension... extensions) { + String directoryName = methodName; + if (!serverId.equals("default")) { + directoryName += "_" + serverId; + } + + final Options localOptions = new WireMockRuleConfiguration(WireMockMultiServerRule.this.options, + directoryName, + extensions); + + new File(localOptions.filesRoot().getPath(), "mappings").mkdirs(); + new File(localOptions.filesRoot().getPath(), "__files").mkdirs(); + + WireMockServer server = new WireMockServer(localOptions); + this.servers.put(serverId, server); + server.start(); + + if (!serverId.equals("default")) { + WireMock.configureFor("localhost", server.port()); + } + } + + /** + * Before. + */ + protected void before() { + } + + /** + * After. + */ + protected void after() { + } + private void checkForUnmatchedRequests() { servers.values().forEach(server -> checkForUnmatchedRequests(server)); } @@ -168,52 +216,4 @@ private void stop() { }); } - /** - * After. - */ - protected void after() { - } - - /** - * Before. - */ - protected void before() { - } - - /** - * Initialize server. - * - * @param serverId - * the server id - * @param extensions - * the extensions - */ - protected final void initializeServer(String serverId, Extension... extensions) { - String directoryName = methodName; - if (!serverId.equals("default")) { - directoryName += "_" + serverId; - } - - final Options localOptions = new WireMockRuleConfiguration(WireMockMultiServerRule.this.options, - directoryName, - extensions); - - new File(localOptions.filesRoot().getPath(), "mappings").mkdirs(); - new File(localOptions.filesRoot().getPath(), "__files").mkdirs(); - - WireMockServer server = new WireMockServer(localOptions); - this.servers.put(serverId, server); - server.start(); - - if (!serverId.equals("default")) { - WireMock.configureFor("localhost", server.port()); - } - } - - /** - * Initialize servers. - */ - protected void initializeServers() { - } - } diff --git a/src/test/java/org/kohsuke/github/WireMockRule.java b/src/test/java/org/kohsuke/github/WireMockRule.java index a20984a44f..66f2baf6dc 100644 --- a/src/test/java/org/kohsuke/github/WireMockRule.java +++ b/src/test/java/org/kohsuke/github/WireMockRule.java @@ -41,19 +41,21 @@ */ public class WireMockRule implements MethodRule, TestRule, Container, Stubbing, Admin { + private WireMockServer wireMockServer; private boolean failOnUnmatchedRequests; - private String methodName = null; private final Options options; - private WireMockServer wireMockServer; - /** - * Instantiates a new wire mock rule. + * Gets the method name. + * + * @return the method name */ - public WireMockRule() { - this(WireMockRuleConfiguration.wireMockConfig()); + public String getMethodName() { + return methodName; } + private String methodName = null; + /** * Instantiates a new wire mock rule. * @@ -100,23 +102,10 @@ public WireMockRule(int port, Integer httpsPort) { } /** - * Adds the mock service request listener. - * - * @param listener - * the listener - */ - public void addMockServiceRequestListener(RequestListener listener) { - wireMockServer.addMockServiceRequestListener(listener); - } - - /** - * Adds the stub mapping. - * - * @param stubMapping - * the stub mapping + * Instantiates a new wire mock rule. */ - public void addStubMapping(StubMapping stubMapping) { - wireMockServer.addStubMapping(stubMapping); + public WireMockRule() { + this(WireMockRuleConfiguration.wireMockConfig()); } /** @@ -147,44 +136,87 @@ public Statement apply(final Statement base, FrameworkMethod method, Object targ return this.apply(base, method.getName()); } + private Statement apply(final Statement base, final String methodName) { + return new Statement() { + public void evaluate() throws Throwable { + WireMockRule.this.methodName = methodName; + final Options localOptions = new WireMockRuleConfiguration(WireMockRule.this.options, methodName); + + new File(localOptions.filesRoot().getPath(), "mappings").mkdirs(); + new File(localOptions.filesRoot().getPath(), "__files").mkdirs(); + + WireMockRule.this.wireMockServer = new WireMockServer(localOptions); + WireMockRule.this.start(); + WireMock.configureFor("localhost", WireMockRule.this.port()); + + try { + WireMockRule.this.before(); + base.evaluate(); + WireMockRule.this.checkForUnmatchedRequests(); + } finally { + WireMockRule.this.after(); + WireMockRule.this.stop(); + WireMockRule.this.methodName = null; + } + + } + }; + } + + private void checkForUnmatchedRequests() { + if (this.failOnUnmatchedRequests) { + List unmatchedRequests = this.findAllUnmatchedRequests(); + if (!unmatchedRequests.isEmpty()) { + List nearMisses = this.findNearMissesForAllUnmatchedRequests(); + if (nearMisses.isEmpty()) { + throw VerificationException.forUnmatchedRequests(unmatchedRequests); + } + + throw VerificationException.forUnmatchedNearMisses(nearMisses); + } + } + + } + /** - * Base url. - * - * @return the string + * Before. */ - public String baseUrl() { - return wireMockServer.baseUrl(); + protected void before() { } /** - * Count requests matching. + * After. + */ + protected void after() { + } + + /** + * Load mappings using. * - * @param requestPattern - * the request pattern - * @return the verification result + * @param mappingsLoader + * the mappings loader */ - public VerificationResult countRequestsMatching(RequestPattern requestPattern) { - return wireMockServer.countRequestsMatching(requestPattern); + public void loadMappingsUsing(MappingsLoader mappingsLoader) { + wireMockServer.loadMappingsUsing(mappingsLoader); } /** - * Edits the stub. + * Gets the global settings holder. * - * @param mappingBuilder - * the mapping builder + * @return the global settings holder */ - public void editStub(MappingBuilder mappingBuilder) { - wireMockServer.editStub(mappingBuilder); + public GlobalSettingsHolder getGlobalSettingsHolder() { + return wireMockServer.getGlobalSettingsHolder(); } /** - * Edits the stub mapping. + * Adds the mock service request listener. * - * @param stubMapping - * the stub mapping + * @param listener + * the listener */ - public void editStubMapping(StubMapping stubMapping) { - wireMockServer.editStubMapping(stubMapping); + public void addMockServiceRequestListener(RequestListener listener) { + wireMockServer.addMockServiceRequestListener(listener); } /** @@ -200,221 +232,132 @@ public void enableRecordMappings(FileSource mappingsFileSource, FileSource files } /** - * Find all. - * - * @param requestPatternBuilder - * the request pattern builder - * @return the list + * Stop. */ - public List findAll(RequestPatternBuilder requestPatternBuilder) { - return wireMockServer.findAll(requestPatternBuilder); + public void stop() { + wireMockServer.stop(); } /** - * Find all near misses for. - * - * @param requestPatternBuilder - * the request pattern builder - * @return the list + * Start. */ - public List findAllNearMissesFor(RequestPatternBuilder requestPatternBuilder) { - return wireMockServer.findAllNearMissesFor(requestPatternBuilder); + public void start() { + wireMockServer.start(); } /** - * Find all stubs by metadata. - * - * @param pattern - * the pattern - * @return the list stub mappings result + * Shutdown. */ - public ListStubMappingsResult findAllStubsByMetadata(StringValuePattern pattern) { - return wireMockServer.findAllStubsByMetadata(pattern); + public void shutdown() { + wireMockServer.shutdown(); } /** - * Find all unmatched requests. + * Port. * - * @return the list + * @return the int */ - public List findAllUnmatchedRequests() { - return wireMockServer.findAllUnmatchedRequests(); + public int port() { + return wireMockServer.port(); } /** - * Find near misses for. + * Https port. * - * @param loggedRequest - * the logged request - * @return the list + * @return the int */ - public List findNearMissesFor(LoggedRequest loggedRequest) { - return wireMockServer.findNearMissesFor(loggedRequest); + public int httpsPort() { + return wireMockServer.httpsPort(); } /** - * Find near misses for all unmatched requests. + * Url. * - * @return the list + * @param path + * the path + * @return the string */ - public List findNearMissesForAllUnmatchedRequests() { - return wireMockServer.findNearMissesForAllUnmatchedRequests(); + public String url(String path) { + return wireMockServer.url(path); } /** - * Find near misses for unmatched requests. + * Base url. * - * @return the find near misses result + * @return the string */ - public FindNearMissesResult findNearMissesForUnmatchedRequests() { - return wireMockServer.findNearMissesForUnmatchedRequests(); + public String baseUrl() { + return wireMockServer.baseUrl(); } /** - * Find requests matching. + * Checks if is running. * - * @param requestPattern - * the request pattern - * @return the find requests result + * @return true, if is running */ - public FindRequestsResult findRequestsMatching(RequestPattern requestPattern) { - return wireMockServer.findRequestsMatching(requestPattern); + public boolean isRunning() { + return wireMockServer.isRunning(); } /** - * Find stub mappings by metadata. + * Given that. * - * @param pattern - * the pattern - * @return the list + * @param mappingBuilder + * the mapping builder + * @return the stub mapping */ - public List findStubMappingsByMetadata(StringValuePattern pattern) { - return wireMockServer.findStubMappingsByMetadata(pattern); + public StubMapping givenThat(MappingBuilder mappingBuilder) { + return wireMockServer.givenThat(mappingBuilder); } /** - * Find top near misses for. + * Stub for. * - * @param loggedRequest - * the logged request - * @return the find near misses result + * @param mappingBuilder + * the mapping builder + * @return the stub mapping */ - public FindNearMissesResult findTopNearMissesFor(LoggedRequest loggedRequest) { - return wireMockServer.findTopNearMissesFor(loggedRequest); + public StubMapping stubFor(MappingBuilder mappingBuilder) { + return wireMockServer.stubFor(mappingBuilder); } /** - * Find top near misses for. + * Edits the stub. * - * @param requestPattern - * the request pattern - * @return the find near misses result + * @param mappingBuilder + * the mapping builder */ - public FindNearMissesResult findTopNearMissesFor(RequestPattern requestPattern) { - return wireMockServer.findTopNearMissesFor(requestPattern); + public void editStub(MappingBuilder mappingBuilder) { + wireMockServer.editStub(mappingBuilder); } /** - * Find unmatched requests. + * Removes the stub. * - * @return the find requests result + * @param mappingBuilder + * the mapping builder */ - public FindRequestsResult findUnmatchedRequests() { - return wireMockServer.findUnmatchedRequests(); + public void removeStub(MappingBuilder mappingBuilder) { + wireMockServer.removeStub(mappingBuilder); } /** - * Gets the all scenarios. + * Removes the stub. * - * @return the all scenarios + * @param stubMapping + * the stub mapping */ - public GetScenariosResult getAllScenarios() { - return wireMockServer.getAllScenarios(); + public void removeStub(StubMapping stubMapping) { + wireMockServer.removeStub(stubMapping); } /** - * Gets the all serve events. + * Gets the stub mappings. * - * @return the all serve events + * @return the stub mappings */ - public List getAllServeEvents() { - return wireMockServer.getAllServeEvents(); - } - - /** - * Gets the global settings. - * - * @return the global settings - */ - public GetGlobalSettingsResult getGlobalSettings() { - return wireMockServer.getGlobalSettings(); - } - - /** - * Gets the global settings holder. - * - * @return the global settings holder - */ - public GlobalSettingsHolder getGlobalSettingsHolder() { - return wireMockServer.getGlobalSettingsHolder(); - } - - /** - * Gets the method name. - * - * @return the method name - */ - public String getMethodName() { - return methodName; - } - - /** - * Gets the options. - * - * @return the options - */ - public Options getOptions() { - return wireMockServer.getOptions(); - } - - /** - * Gets the recording status. - * - * @return the recording status - */ - public RecordingStatusResult getRecordingStatus() { - return wireMockServer.getRecordingStatus(); - } - - /** - * Gets the serve events. - * - * @return the serve events - */ - public GetServeEventsResult getServeEvents() { - return wireMockServer.getServeEvents(); - } - - /** - * Gets the serve events. - * - * @param serveEventQuery - * the serve event query - * @return the serve events - */ - public GetServeEventsResult getServeEvents(ServeEventQuery serveEventQuery) { - return wireMockServer.getServeEvents(serveEventQuery); - } - - /** - * Gets the served stub. - * - * @param id - * the id - * @return the served stub - */ - public SingleServedStubResult getServedStub(UUID id) { - return wireMockServer.getServedStub(id); + public List getStubMappings() { + return wireMockServer.getStubMappings(); } /** @@ -429,152 +372,158 @@ public StubMapping getSingleStubMapping(UUID id) { } /** - * Gets the stub mapping. + * Find stub mappings by metadata. * - * @param id - * the id - * @return the stub mapping + * @param pattern + * the pattern + * @return the list */ - public SingleStubMappingResult getStubMapping(UUID id) { - return wireMockServer.getStubMapping(id); + public List findStubMappingsByMetadata(StringValuePattern pattern) { + return wireMockServer.findStubMappingsByMetadata(pattern); } /** - * Gets the stub mappings. + * Removes the stub mappings by metadata. * - * @return the stub mappings + * @param pattern + * the pattern */ - public List getStubMappings() { - return wireMockServer.getStubMappings(); + public void removeStubMappingsByMetadata(StringValuePattern pattern) { + wireMockServer.removeStubMappingsByMetadata(pattern); } /** - * Given that. + * Removes the stub mapping. * - * @param mappingBuilder - * the mapping builder - * @return the stub mapping + * @param stubMapping + * the stub mapping */ - public StubMapping givenThat(MappingBuilder mappingBuilder) { - return wireMockServer.givenThat(mappingBuilder); + public void removeStubMapping(StubMapping stubMapping) { + wireMockServer.removeStubMapping(stubMapping); } /** - * Https port. + * Verify. * - * @return the int + * @param requestPatternBuilder + * the request pattern builder */ - public int httpsPort() { - return wireMockServer.httpsPort(); + public void verify(RequestPatternBuilder requestPatternBuilder) { + wireMockServer.verify(requestPatternBuilder); } /** - * Import stubs. + * Verify. * - * @param stubImport - * the stub import + * @param count + * the count + * @param requestPatternBuilder + * the request pattern builder */ - public void importStubs(StubImport stubImport) { - wireMockServer.importStubs(stubImport); + public void verify(int count, RequestPatternBuilder requestPatternBuilder) { + wireMockServer.verify(count, requestPatternBuilder); } /** - * Checks if is running. + * Verify. * - * @return true, if is running + * @param countMatchingStrategy + * the count matching strategy + * @param requestPatternBuilder + * the request pattern builder */ - public boolean isRunning() { - return wireMockServer.isRunning(); + public void verify(CountMatchingStrategy countMatchingStrategy, RequestPatternBuilder requestPatternBuilder) { + wireMockServer.verify(countMatchingStrategy, requestPatternBuilder); } /** - * List all stub mappings. + * Find all. * - * @return the list stub mappings result + * @param requestPatternBuilder + * the request pattern builder + * @return the list */ - public ListStubMappingsResult listAllStubMappings() { - return wireMockServer.listAllStubMappings(); + public List findAll(RequestPatternBuilder requestPatternBuilder) { + return wireMockServer.findAll(requestPatternBuilder); } /** - * Load mappings using. + * Gets the all serve events. * - * @param mappingsLoader - * the mappings loader + * @return the all serve events */ - public void loadMappingsUsing(MappingsLoader mappingsLoader) { - wireMockServer.loadMappingsUsing(mappingsLoader); + public List getAllServeEvents() { + return wireMockServer.getAllServeEvents(); } /** - * Port. + * Sets the global fixed delay. * - * @return the int + * @param milliseconds + * the new global fixed delay */ - public int port() { - return wireMockServer.port(); + public void setGlobalFixedDelay(int milliseconds) { + wireMockServer.setGlobalFixedDelay(milliseconds); } /** - * Removes the serve event. + * Find all unmatched requests. * - * @param uuid - * the uuid + * @return the list */ - public void removeServeEvent(UUID uuid) { - wireMockServer.removeServeEvent(uuid); + public List findAllUnmatchedRequests() { + return wireMockServer.findAllUnmatchedRequests(); } /** - * Removes the serve events for stubs matching metadata. + * Find near misses for all unmatched requests. * - * @param stringValuePattern - * the string value pattern - * @return the find serve events result + * @return the list */ - public FindServeEventsResult removeServeEventsForStubsMatchingMetadata(StringValuePattern stringValuePattern) { - return wireMockServer.removeServeEventsForStubsMatchingMetadata(stringValuePattern); + public List findNearMissesForAllUnmatchedRequests() { + return wireMockServer.findNearMissesForAllUnmatchedRequests(); } /** - * Removes the serve events matching. + * Find all near misses for. * - * @param requestPattern - * the request pattern - * @return the find serve events result + * @param requestPatternBuilder + * the request pattern builder + * @return the list */ - public FindServeEventsResult removeServeEventsMatching(RequestPattern requestPattern) { - return wireMockServer.removeServeEventsMatching(requestPattern); + public List findAllNearMissesFor(RequestPatternBuilder requestPatternBuilder) { + return wireMockServer.findAllNearMissesFor(requestPatternBuilder); } /** - * Removes the stub. + * Find near misses for. * - * @param mappingBuilder - * the mapping builder + * @param loggedRequest + * the logged request + * @return the list */ - public void removeStub(MappingBuilder mappingBuilder) { - wireMockServer.removeStub(mappingBuilder); + public List findNearMissesFor(LoggedRequest loggedRequest) { + return wireMockServer.findNearMissesFor(loggedRequest); } /** - * Removes the stub. + * Adds the stub mapping. * * @param stubMapping * the stub mapping */ - public void removeStub(StubMapping stubMapping) { - wireMockServer.removeStub(stubMapping); + public void addStubMapping(StubMapping stubMapping) { + wireMockServer.addStubMapping(stubMapping); } /** - * Removes the stub mapping. + * Edits the stub mapping. * * @param stubMapping * the stub mapping */ - public void removeStubMapping(StubMapping stubMapping) { - wireMockServer.removeStubMapping(stubMapping); + public void editStubMapping(StubMapping stubMapping) { + wireMockServer.editStubMapping(stubMapping); } /** @@ -588,37 +537,37 @@ public void removeStubMapping(UUID id) { } /** - * Removes the stub mappings by metadata. + * List all stub mappings. * - * @param pattern - * the pattern + * @return the list stub mappings result */ - public void removeStubMappingsByMetadata(StringValuePattern pattern) { - wireMockServer.removeStubMappingsByMetadata(pattern); + public ListStubMappingsResult listAllStubMappings() { + return wireMockServer.listAllStubMappings(); } /** - * Removes the stubs by metadata. + * Gets the stub mapping. * - * @param pattern - * the pattern + * @param id + * the id + * @return the stub mapping */ - public void removeStubsByMetadata(StringValuePattern pattern) { - wireMockServer.removeStubsByMetadata(pattern); + public SingleStubMappingResult getStubMapping(UUID id) { + return wireMockServer.getStubMapping(id); } /** - * Reset all. + * Save mappings. */ - public void resetAll() { - wireMockServer.resetAll(); + public void saveMappings() { + wireMockServer.saveMappings(); } /** - * Reset mappings. + * Reset all. */ - public void resetMappings() { - wireMockServer.resetMappings(); + public void resetAll() { + wireMockServer.resetAll(); } /** @@ -629,13 +578,41 @@ public void resetRequests() { } /** - * Reset a scenario - * - * @param name - * the name + * Reset to default mappings. */ - public void resetScenario(String name) { - wireMockServer.resetScenario(name); + public void resetToDefaultMappings() { + wireMockServer.resetToDefaultMappings(); + } + + /** + * Gets the serve events. + * + * @return the serve events + */ + public GetServeEventsResult getServeEvents() { + return wireMockServer.getServeEvents(); + } + + /** + * Gets the serve events. + * + * @param serveEventQuery + * the serve event query + * @return the serve events + */ + public GetServeEventsResult getServeEvents(ServeEventQuery serveEventQuery) { + return wireMockServer.getServeEvents(serveEventQuery); + } + + /** + * Gets the served stub. + * + * @param id + * the id + * @return the served stub + */ + public SingleServedStubResult getServedStub(UUID id) { + return wireMockServer.getServedStub(id); } /** @@ -646,111 +623,145 @@ public void resetScenarios() { } /** - * Reset to default mappings. + * Reset mappings. */ - public void resetToDefaultMappings() { - wireMockServer.resetToDefaultMappings(); + public void resetMappings() { + wireMockServer.resetMappings(); } /** - * Save mappings. + * Count requests matching. + * + * @param requestPattern + * the request pattern + * @return the verification result */ - public void saveMappings() { - wireMockServer.saveMappings(); + public VerificationResult countRequestsMatching(RequestPattern requestPattern) { + return wireMockServer.countRequestsMatching(requestPattern); } /** - * Sets the global fixed delay. + * Find requests matching. * - * @param milliseconds - * the new global fixed delay + * @param requestPattern + * the request pattern + * @return the find requests result */ - public void setGlobalFixedDelay(int milliseconds) { - wireMockServer.setGlobalFixedDelay(milliseconds); + public FindRequestsResult findRequestsMatching(RequestPattern requestPattern) { + return wireMockServer.findRequestsMatching(requestPattern); } /** - * Set scenario state + * Find unmatched requests. * - * @param name - * the name - * @param state - * the state + * @return the find requests result */ - public void setScenarioState(String name, String state) { - wireMockServer.setScenarioState(name, state); + public FindRequestsResult findUnmatchedRequests() { + return wireMockServer.findUnmatchedRequests(); } /** - * Shutdown. + * Removes the serve event. + * + * @param uuid + * the uuid */ - public void shutdown() { - wireMockServer.shutdown(); + public void removeServeEvent(UUID uuid) { + wireMockServer.removeServeEvent(uuid); } /** - * Shutdown server. + * Removes the serve events matching. + * + * @param requestPattern + * the request pattern + * @return the find serve events result */ - public void shutdownServer() { - wireMockServer.shutdownServer(); + public FindServeEventsResult removeServeEventsMatching(RequestPattern requestPattern) { + return wireMockServer.removeServeEventsMatching(requestPattern); } /** - * Snapshot record. + * Removes the serve events for stubs matching metadata. * - * @return the snapshot record result + * @param stringValuePattern + * the string value pattern + * @return the find serve events result */ - public SnapshotRecordResult snapshotRecord() { - return wireMockServer.snapshotRecord(); + public FindServeEventsResult removeServeEventsForStubsMatchingMetadata(StringValuePattern stringValuePattern) { + return wireMockServer.removeServeEventsForStubsMatchingMetadata(stringValuePattern); } /** - * Snapshot record. + * Update global settings. * - * @param spec - * the spec - * @return the snapshot record result + * @param newSettings + * the new settings */ - public SnapshotRecordResult snapshotRecord(RecordSpec spec) { - return wireMockServer.snapshotRecord(spec); + public void updateGlobalSettings(GlobalSettings newSettings) { + wireMockServer.updateGlobalSettings(newSettings); } /** - * Snapshot record. + * Find near misses for unmatched requests. * - * @param spec - * the spec - * @return the snapshot record result + * @return the find near misses result */ - public SnapshotRecordResult snapshotRecord(RecordSpecBuilder spec) { - return wireMockServer.snapshotRecord(spec); + public FindNearMissesResult findNearMissesForUnmatchedRequests() { + return wireMockServer.findNearMissesForUnmatchedRequests(); } /** - * Start. + * Gets the all scenarios. + * + * @return the all scenarios */ - public void start() { - wireMockServer.start(); + public GetScenariosResult getAllScenarios() { + return wireMockServer.getAllScenarios(); } /** - * Start recording. + * Reset a scenario * - * @param spec - * the spec + * @param name + * the name */ - public void startRecording(RecordSpec spec) { - wireMockServer.startRecording(spec); + public void resetScenario(String name) { + wireMockServer.resetScenario(name); } /** - * Start recording. + * Set scenario state * - * @param recordSpec - * the record spec + * @param name + * the name + * @param state + * the state */ - public void startRecording(RecordSpecBuilder recordSpec) { - wireMockServer.startRecording(recordSpec); + public void setScenarioState(String name, String state) { + wireMockServer.setScenarioState(name, state); + } + + /** + * Find top near misses for. + * + * @param loggedRequest + * the logged request + * @return the find near misses result + */ + public FindNearMissesResult findTopNearMissesFor(LoggedRequest loggedRequest) { + return wireMockServer.findTopNearMissesFor(loggedRequest); + } + + /** + * Find top near misses for. + * + * @param requestPattern + * the request pattern + * @return the find near misses result + */ + public FindNearMissesResult findTopNearMissesFor(RequestPattern requestPattern) { + return wireMockServer.findTopNearMissesFor(requestPattern); } /** @@ -764,10 +775,23 @@ public void startRecording(String targetBaseUrl) { } /** - * Stop. + * Start recording. + * + * @param spec + * the spec */ - public void stop() { - wireMockServer.stop(); + public void startRecording(RecordSpec spec) { + wireMockServer.startRecording(spec); + } + + /** + * Start recording. + * + * @param recordSpec + * the record spec + */ + public void startRecording(RecordSpecBuilder recordSpec) { + wireMockServer.startRecording(recordSpec); } /** @@ -780,122 +804,98 @@ public SnapshotRecordResult stopRecording() { } /** - * Stub for. + * Gets the recording status. * - * @param mappingBuilder - * the mapping builder - * @return the stub mapping + * @return the recording status */ - public StubMapping stubFor(MappingBuilder mappingBuilder) { - return wireMockServer.stubFor(mappingBuilder); + public RecordingStatusResult getRecordingStatus() { + return wireMockServer.getRecordingStatus(); } /** - * Update global settings. + * Snapshot record. * - * @param newSettings - * the new settings + * @return the snapshot record result */ - public void updateGlobalSettings(GlobalSettings newSettings) { - wireMockServer.updateGlobalSettings(newSettings); + public SnapshotRecordResult snapshotRecord() { + return wireMockServer.snapshotRecord(); } /** - * Url. + * Snapshot record. * - * @param path - * the path - * @return the string + * @param spec + * the spec + * @return the snapshot record result */ - public String url(String path) { - return wireMockServer.url(path); + public SnapshotRecordResult snapshotRecord(RecordSpecBuilder spec) { + return wireMockServer.snapshotRecord(spec); } /** - * Verify. + * Snapshot record. * - * @param countMatchingStrategy - * the count matching strategy - * @param requestPatternBuilder - * the request pattern builder + * @param spec + * the spec + * @return the snapshot record result */ - public void verify(CountMatchingStrategy countMatchingStrategy, RequestPatternBuilder requestPatternBuilder) { - wireMockServer.verify(countMatchingStrategy, requestPatternBuilder); + public SnapshotRecordResult snapshotRecord(RecordSpec spec) { + return wireMockServer.snapshotRecord(spec); } /** - * Verify. + * Gets the options. * - * @param requestPatternBuilder - * the request pattern builder + * @return the options */ - public void verify(RequestPatternBuilder requestPatternBuilder) { - wireMockServer.verify(requestPatternBuilder); + public Options getOptions() { + return wireMockServer.getOptions(); } /** - * Verify. - * - * @param count - * the count - * @param requestPatternBuilder - * the request pattern builder + * Shutdown server. */ - public void verify(int count, RequestPatternBuilder requestPatternBuilder) { - wireMockServer.verify(count, requestPatternBuilder); + public void shutdownServer() { + wireMockServer.shutdownServer(); } - private Statement apply(final Statement base, final String methodName) { - return new Statement() { - public void evaluate() throws Throwable { - WireMockRule.this.methodName = methodName; - final Options localOptions = new WireMockRuleConfiguration(WireMockRule.this.options, methodName); - - new File(localOptions.filesRoot().getPath(), "mappings").mkdirs(); - new File(localOptions.filesRoot().getPath(), "__files").mkdirs(); - - WireMockRule.this.wireMockServer = new WireMockServer(localOptions); - WireMockRule.this.start(); - WireMock.configureFor("localhost", WireMockRule.this.port()); - - try { - WireMockRule.this.before(); - base.evaluate(); - WireMockRule.this.checkForUnmatchedRequests(); - } finally { - WireMockRule.this.after(); - WireMockRule.this.stop(); - WireMockRule.this.methodName = null; - } - - } - }; + /** + * Find all stubs by metadata. + * + * @param pattern + * the pattern + * @return the list stub mappings result + */ + public ListStubMappingsResult findAllStubsByMetadata(StringValuePattern pattern) { + return wireMockServer.findAllStubsByMetadata(pattern); } - private void checkForUnmatchedRequests() { - if (this.failOnUnmatchedRequests) { - List unmatchedRequests = this.findAllUnmatchedRequests(); - if (!unmatchedRequests.isEmpty()) { - List nearMisses = this.findNearMissesForAllUnmatchedRequests(); - if (nearMisses.isEmpty()) { - throw VerificationException.forUnmatchedRequests(unmatchedRequests); - } - - throw VerificationException.forUnmatchedNearMisses(nearMisses); - } - } - + /** + * Removes the stubs by metadata. + * + * @param pattern + * the pattern + */ + public void removeStubsByMetadata(StringValuePattern pattern) { + wireMockServer.removeStubsByMetadata(pattern); } /** - * After. + * Import stubs. + * + * @param stubImport + * the stub import */ - protected void after() { + public void importStubs(StubImport stubImport) { + wireMockServer.importStubs(stubImport); } /** - * Before. + * Gets the global settings. + * + * @return the global settings */ - protected void before() { + public GetGlobalSettingsResult getGlobalSettings() { + return wireMockServer.getGlobalSettings(); } } diff --git a/src/test/java/org/kohsuke/github/WireMockRuleConfiguration.java b/src/test/java/org/kohsuke/github/WireMockRuleConfiguration.java index 1d8f2c305e..c933f885f4 100644 --- a/src/test/java/org/kohsuke/github/WireMockRuleConfiguration.java +++ b/src/test/java/org/kohsuke/github/WireMockRuleConfiguration.java @@ -27,28 +27,10 @@ */ public class WireMockRuleConfiguration implements Options { - /** - * Options. - * - * @return the wire mock rule configuration - */ - public static WireMockRuleConfiguration options() { - return wireMockConfig(); - } - /** - * Wire mock config. - * - * @return the wire mock rule configuration - */ - public static WireMockRuleConfiguration wireMockConfig() { - return new WireMockRuleConfiguration(); - } + private final Options parent; private final String childDirectory; - private Map extensions = Maps.newLinkedHashMap(); - private MappingsSource mappingsSource; - - private final Options parent; + private Map extensions = Maps.newLinkedHashMap(); /** * Instantiates a new wire mock rule configuration. @@ -74,194 +56,214 @@ public static WireMockRuleConfiguration wireMockConfig() { } /** - * Bind address. + * Wire mock config. * - * @return the string + * @return the wire mock rule configuration */ - public String bindAddress() { - return parent.bindAddress(); + public static WireMockRuleConfiguration wireMockConfig() { + return new WireMockRuleConfiguration(); } /** - * Browser proxy settings. + * Options. * - * @return the browser proxy settings + * @return the wire mock rule configuration */ - public BrowserProxySettings browserProxySettings() { - return parent.browserProxySettings(); + public static WireMockRuleConfiguration options() { + return wireMockConfig(); } /** - * Browser proxying enabled. + * For child path. * - * @return true, if successful + * @param childPath + * the child path + * @return the wire mock rule configuration */ - public boolean browserProxyingEnabled() { - return parent.browserProxyingEnabled(); + public WireMockRuleConfiguration forChildPath(String childPath) { + return new WireMockRuleConfiguration(this, childPath); + } + + private MappingsSource getMappingsSource() { + if (this.mappingsSource == null) { + this.mappingsSource = new JsonFileMappingsSource(this.filesRoot().child("mappings")); + } + + return this.mappingsSource; } /** - * Container threads. + * Files root. * - * @return the int + * @return the file source */ - public int containerThreads() { - return parent.containerThreads(); + public FileSource filesRoot() { + return childDirectory != null ? parent.filesRoot().child(childDirectory) : parent.filesRoot(); } /** - * Extensions of type. + * Mappings loader. * - * @param - * the generic type - * @param extensionType - * the extension type - * @return the map + * @return the mappings loader */ - public Map extensionsOfType(Class extensionType) { - Map result = Maps.newLinkedHashMap(this.parent.extensionsOfType(extensionType)); - result.putAll((Map) Maps.filterEntries(this.extensions, - ExtensionLoader.valueAssignableFrom(extensionType))); - return result; + public MappingsLoader mappingsLoader() { + return this.getMappingsSource(); } /** - * Files root. + * Mappings saver. * - * @return the file source + * @return the mappings saver */ - public FileSource filesRoot() { - return childDirectory != null ? parent.filesRoot().child(childDirectory) : parent.filesRoot(); + public MappingsSaver mappingsSaver() { + return this.getMappingsSource(); } /** - * For child path. + * Mapping source. * - * @param childPath - * the child path + * @param mappingsSource + * the mappings source * @return the wire mock rule configuration */ - public WireMockRuleConfiguration forChildPath(String childPath) { - return new WireMockRuleConfiguration(this, childPath); + public WireMockRuleConfiguration mappingSource(MappingsSource mappingsSource) { + this.mappingsSource = mappingsSource; + return this; + } + + /** + * Extensions of type. + * + * @param + * the generic type + * @param extensionType + * the extension type + * @return the map + */ + public Map extensionsOfType(Class extensionType) { + Map result = Maps.newLinkedHashMap(this.parent.extensionsOfType(extensionType)); + result.putAll((Map) Maps.filterEntries(this.extensions, + ExtensionLoader.valueAssignableFrom(extensionType))); + return result; } // Simple wrappers /** - * Gets the admin authenticator. + * Port number. * - * @return the admin authenticator + * @return the int */ - public Authenticator getAdminAuthenticator() { - return parent.getAdminAuthenticator(); + public int portNumber() { + return parent.portNumber(); } /** - * Gets the asynchronous response settings. + * Gets the http disabled. * - * @return the asynchronous response settings + * @return the http disabled */ - public AsynchronousResponseSettings getAsynchronousResponseSettings() { - return parent.getAsynchronousResponseSettings(); + public boolean getHttpDisabled() { + return parent.getHttpDisabled(); } /** - * Gets the chunked encoding policy. + * Container threads. * - * @return the chunked encoding policy + * @return the int */ - public ChunkedEncodingPolicy getChunkedEncodingPolicy() { - return parent.getChunkedEncodingPolicy(); + public int containerThreads() { + return parent.containerThreads(); } /** - * Gets the data truncation settings. + * Https settings. * - * @return the data truncation settings + * @return the https settings */ - public DataTruncationSettings getDataTruncationSettings() { - return parent.getDataTruncationSettings(); + public HttpsSettings httpsSettings() { + return parent.httpsSettings(); } /** - * Gets the disable optimize xml factories loading. + * Jetty settings. * - * @return the disable optimize xml factories loading + * @return the jetty settings */ - public boolean getDisableOptimizeXmlFactoriesLoading() { - return parent.getDisableOptimizeXmlFactoriesLoading(); + public JettySettings jettySettings() { + return parent.jettySettings(); } /** - * Gets the disable strict http headers. + * Browser proxying enabled. * - * @return the disable strict http headers + * @return true, if successful */ - public boolean getDisableStrictHttpHeaders() { - return parent.getDisableStrictHttpHeaders(); + public boolean browserProxyingEnabled() { + return parent.browserProxyingEnabled(); } /** - * Gets the gzip disabled. + * Browser proxy settings. * - * @return the gzip disabled + * @return the browser proxy settings */ - public boolean getGzipDisabled() { - return parent.getGzipDisabled(); + public BrowserProxySettings browserProxySettings() { + return parent.browserProxySettings(); } /** - * Gets the http disabled. + * Proxy via. * - * @return the http disabled + * @return the proxy settings */ - public boolean getHttpDisabled() { - return parent.getHttpDisabled(); + public ProxySettings proxyVia() { + return parent.proxyVia(); } /** - * Gets the https required for admin api. + * Notifier. * - * @return the https required for admin api + * @return the notifier */ - public boolean getHttpsRequiredForAdminApi() { - return parent.getHttpsRequiredForAdminApi(); + public Notifier notifier() { + return parent.notifier(); } /** - * Gets the not matched renderer. + * Request journal disabled. * - * @return the not matched renderer + * @return true, if successful */ - public NotMatchedRenderer getNotMatchedRenderer() { - return parent.getNotMatchedRenderer(); + public boolean requestJournalDisabled() { + return parent.requestJournalDisabled(); } /** - * Gets the network address rules. + * Max request journal entries. * - * @return the network address rules + * @return the optional */ - public NetworkAddressRules getProxyTargetRules() { - return parent.getProxyTargetRules(); + public Optional maxRequestJournalEntries() { + return parent.maxRequestJournalEntries(); } /** - * Gets the stub cors enabled. + * Bind address. * - * @return the stub cors enabled + * @return the string */ - public boolean getStubCorsEnabled() { - return parent.getStubCorsEnabled(); + public String bindAddress() { + return parent.bindAddress(); } /** - * Gets the stub request logging disabled. + * Matching headers. * - * @return the stub request logging disabled + * @return the list */ - public boolean getStubRequestLoggingDisabled() { - return parent.getStubRequestLoggingDisabled(); + public List matchingHeaders() { + return parent.matchingHeaders(); } /** @@ -274,157 +276,155 @@ public HttpServerFactory httpServerFactory() { } /** - * Https settings. + * Thread pool factory. * - * @return the https settings + * @return the thread pool factory */ - public HttpsSettings httpsSettings() { - return parent.httpsSettings(); + public ThreadPoolFactory threadPoolFactory() { + return parent.threadPoolFactory(); } /** - * Jetty settings. + * Should preserve host header. * - * @return the jetty settings + * @return true, if successful */ - public JettySettings jettySettings() { - return parent.jettySettings(); + public boolean shouldPreserveHostHeader() { + return parent.shouldPreserveHostHeader(); } /** - * Mapping source. + * Proxy host header. * - * @param mappingsSource - * the mappings source - * @return the wire mock rule configuration + * @return the string */ - public WireMockRuleConfiguration mappingSource(MappingsSource mappingsSource) { - this.mappingsSource = mappingsSource; - return this; + public String proxyHostHeader() { + return parent.proxyHostHeader(); } /** - * Mappings loader. + * Network traffic listener. * - * @return the mappings loader + * @return the wiremock network traffic listener */ - public MappingsLoader mappingsLoader() { - return this.getMappingsSource(); + public WiremockNetworkTrafficListener networkTrafficListener() { + return parent.networkTrafficListener(); } /** - * Mappings saver. + * Gets the admin authenticator. * - * @return the mappings saver + * @return the admin authenticator */ - public MappingsSaver mappingsSaver() { - return this.getMappingsSource(); + public Authenticator getAdminAuthenticator() { + return parent.getAdminAuthenticator(); } /** - * Matching headers. + * Gets the https required for admin api. * - * @return the list + * @return the https required for admin api */ - public List matchingHeaders() { - return parent.matchingHeaders(); + public boolean getHttpsRequiredForAdminApi() { + return parent.getHttpsRequiredForAdminApi(); } /** - * Max request journal entries. + * Gets the not matched renderer. * - * @return the optional + * @return the not matched renderer */ - public Optional maxRequestJournalEntries() { - return parent.maxRequestJournalEntries(); + public NotMatchedRenderer getNotMatchedRenderer() { + return parent.getNotMatchedRenderer(); } /** - * Network traffic listener. + * Gets the asynchronous response settings. * - * @return the wiremock network traffic listener + * @return the asynchronous response settings */ - public WiremockNetworkTrafficListener networkTrafficListener() { - return parent.networkTrafficListener(); + public AsynchronousResponseSettings getAsynchronousResponseSettings() { + return parent.getAsynchronousResponseSettings(); } /** - * Notifier. + * Gets the chunked encoding policy. * - * @return the notifier + * @return the chunked encoding policy */ - public Notifier notifier() { - return parent.notifier(); + public ChunkedEncodingPolicy getChunkedEncodingPolicy() { + return parent.getChunkedEncodingPolicy(); } /** - * Port number. + * Gets the gzip disabled. * - * @return the int + * @return the gzip disabled */ - public int portNumber() { - return parent.portNumber(); + public boolean getGzipDisabled() { + return parent.getGzipDisabled(); } /** - * Proxy host header. + * Gets the stub request logging disabled. * - * @return the string + * @return the stub request logging disabled */ - public String proxyHostHeader() { - return parent.proxyHostHeader(); + public boolean getStubRequestLoggingDisabled() { + return parent.getStubRequestLoggingDisabled(); } /** - * Proxy via. + * Gets the stub cors enabled. * - * @return the proxy settings + * @return the stub cors enabled */ - public ProxySettings proxyVia() { - return parent.proxyVia(); + public boolean getStubCorsEnabled() { + return parent.getStubCorsEnabled(); } /** - * Request journal disabled. + * Timeout. * - * @return true, if successful + * @return the long */ - public boolean requestJournalDisabled() { - return parent.requestJournalDisabled(); + public long timeout() { + return parent.timeout(); } /** - * Should preserve host header. + * Gets the disable optimize xml factories loading. * - * @return true, if successful + * @return the disable optimize xml factories loading */ - public boolean shouldPreserveHostHeader() { - return parent.shouldPreserveHostHeader(); + public boolean getDisableOptimizeXmlFactoriesLoading() { + return parent.getDisableOptimizeXmlFactoriesLoading(); } /** - * Thread pool factory. + * Gets the disable strict http headers. * - * @return the thread pool factory + * @return the disable strict http headers */ - public ThreadPoolFactory threadPoolFactory() { - return parent.threadPoolFactory(); + public boolean getDisableStrictHttpHeaders() { + return parent.getDisableStrictHttpHeaders(); } /** - * Timeout. + * Gets the data truncation settings. * - * @return the long + * @return the data truncation settings */ - public long timeout() { - return parent.timeout(); + public DataTruncationSettings getDataTruncationSettings() { + return parent.getDataTruncationSettings(); } - private MappingsSource getMappingsSource() { - if (this.mappingsSource == null) { - this.mappingsSource = new JsonFileMappingsSource(this.filesRoot().child("mappings")); - } - - return this.mappingsSource; + /** + * Gets the network address rules. + * + * @return the network address rules + */ + public NetworkAddressRules getProxyTargetRules() { + return parent.getProxyTargetRules(); } } diff --git a/src/test/java/org/kohsuke/github/WireMockStatusReporterTest.java b/src/test/java/org/kohsuke/github/WireMockStatusReporterTest.java index bdac794e44..eb1a5e143a 100644 --- a/src/test/java/org/kohsuke/github/WireMockStatusReporterTest.java +++ b/src/test/java/org/kohsuke/github/WireMockStatusReporterTest.java @@ -25,6 +25,58 @@ public class WireMockStatusReporterTest extends AbstractGitHubWireMockTest { public WireMockStatusReporterTest() { } + /** + * User when proxying auth correctly configured. + * + * @throws Exception + * the exception + */ + @Test + public void user_whenProxying_AuthCorrectlyConfigured() throws Exception { + snapshotNotAllowed(); + requireProxy("Tests proper configuration when proxying."); + + verifyAuthenticated(gitHub); + + assertThat(gitHub.getClient().getLogin(), not(equalTo(STUBBED_USER_LOGIN))); + + // If this user query fails, either the proxying config has broken (unlikely) + // or your auth settings are not being retrieved from the environment. + // Check your settings. + GHUser user = gitHub.getMyself(); + assertThat(user.getLogin(), notNullValue()); + + System.out.println(); + System.out.println( + "WireMockStatusReporterTest: GitHub proxying and user auth correctly configured for user login: " + + user.getLogin()); + System.out.println(); + } + + /** + * User when not proxying stubbed. + * + * @throws Exception + * the exception + */ + @Test + public void user_whenNotProxying_Stubbed() throws Exception { + snapshotNotAllowed(); + + assumeFalse("Test only valid when not proxying", mockGitHub.isUseProxy()); + + verifyAuthenticated(gitHub); + assertThat(gitHub.getClient().getLogin(), equalTo(STUBBED_USER_LOGIN)); + + GHUser user = gitHub.getMyself(); + // NOTE: the stubbed user does not have to match the login provided from the github object + // github.login is literally just a placeholder when mocking + assertThat(user.getLogin(), not(equalTo(STUBBED_USER_LOGIN))); + assertThat(user.getLogin(), equalTo("stubbed-user-login")); + + // System.out.println("GitHub proxying and user auth correctly configured for user login: " + user.getLogin()); + } + /** * Basic behaviors when not proxying. * @@ -105,62 +157,13 @@ public void BasicBehaviors_whenProxying() throws Exception { } /** - * User when not proxying stubbed. - * - * @throws Exception - * the exception - */ - @Test - public void user_whenNotProxying_Stubbed() throws Exception { - snapshotNotAllowed(); - - assumeFalse("Test only valid when not proxying", mockGitHub.isUseProxy()); - - verifyAuthenticated(gitHub); - assertThat(gitHub.getClient().getLogin(), equalTo(STUBBED_USER_LOGIN)); - - GHUser user = gitHub.getMyself(); - // NOTE: the stubbed user does not have to match the login provided from the github object - // github.login is literally just a placeholder when mocking - assertThat(user.getLogin(), not(equalTo(STUBBED_USER_LOGIN))); - assertThat(user.getLogin(), equalTo("stubbed-user-login")); - - // System.out.println("GitHub proxying and user auth correctly configured for user login: " + user.getLogin()); - } - - /** - * User when proxying auth correctly configured. + * When snapshot ensure proxy. * * @throws Exception * the exception */ @Test - public void user_whenProxying_AuthCorrectlyConfigured() throws Exception { - snapshotNotAllowed(); - requireProxy("Tests proper configuration when proxying."); - - verifyAuthenticated(gitHub); - - assertThat(gitHub.getClient().getLogin(), not(equalTo(STUBBED_USER_LOGIN))); - - // If this user query fails, either the proxying config has broken (unlikely) - // or your auth settings are not being retrieved from the environment. - // Check your settings. - GHUser user = gitHub.getMyself(); - assertThat(user.getLogin(), notNullValue()); - - System.out.println(); - System.out.println( - "WireMockStatusReporterTest: GitHub proxying and user auth correctly configured for user login: " - + user.getLogin()); - System.out.println(); - } - - /** - * When snapshot ensure proxy. - */ - @Test - public void whenSnapshot_EnsureProxy() { + public void whenSnapshot_EnsureProxy() throws Exception { assumeTrue("Test only valid when Snapshotting (-Dtest.github.takeSnapshot to enable)", mockGitHub.isTakeSnapshot()); @@ -169,10 +172,13 @@ public void whenSnapshot_EnsureProxy() { /** * When snapshot ensure record to expected location. + * + * @throws Exception + * the exception */ @Ignore("Not implemented yet") @Test - public void whenSnapshot_EnsureRecordToExpectedLocation() { + public void whenSnapshot_EnsureRecordToExpectedLocation() throws Exception { assumeTrue("Test only valid when Snapshotting (-Dtest.github.takeSnapshot to enable)", mockGitHub.isTakeSnapshot()); diff --git a/src/test/java/org/kohsuke/github/connector/GitHubConnectorResponseTest.java b/src/test/java/org/kohsuke/github/connector/GitHubConnectorResponseTest.java deleted file mode 100644 index daef1d758f..0000000000 --- a/src/test/java/org/kohsuke/github/connector/GitHubConnectorResponseTest.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.kohsuke.github.connector; - -import com.fasterxml.jackson.databind.util.ByteBufferBackedInputStream; -import org.apache.commons.io.IOUtils; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.junit.Assert; -import org.junit.Test; -import org.kohsuke.github.AbstractGitHubWireMockTest; -import org.kohsuke.github.connector.GitHubConnectorResponse.ByteArrayResponse; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.isA; - -/** - * Test GitHubConnectorResponse - */ -public class GitHubConnectorResponseTest extends AbstractGitHubWireMockTest { - - // Extend ByteArrayResponse to preserve test coverage - private static class CustomBodyGitHubConnectorResponse extends ByteArrayResponse { - private final InputStream stream; - - CustomBodyGitHubConnectorResponse(int statusCode, InputStream stream) { - super(EMPTY_REQUEST, statusCode, new HashMap<>()); - this.stream = stream; - } - - @Override - protected InputStream rawBodyStream() throws IOException { - return stream; - } - } - - /** - * Empty request for response testing. - */ - public static final GitHubConnectorRequest EMPTY_REQUEST = new GitHubConnectorRequest() { - @NotNull @Override - public Map> allHeaders() { - return null; - } - - @Nullable @Override - public InputStream body() { - return null; - } - - @Nullable @Override - public String contentType() { - return null; - } - - @Override - public boolean hasBody() { - return false; - } - - @Nullable @Override - public String header(String name) { - return null; - } - - @NotNull @Override - public String method() { - return null; - } - - @NotNull @Override - public URL url() { - return null; - } - }; - - /** - * Instantiates a new GitHubConnectorResponseTest. - */ - public GitHubConnectorResponseTest() { - } - - /** - * Test forced rereadable body stream. - * - * @throws Exception - * for failures - */ - @Test - public void tesBodyStream_forced() throws Exception { - Exception e; - GitHubConnectorResponse response = new CustomBodyGitHubConnectorResponse(200, - new ByteBufferBackedInputStream(ByteBuffer.wrap("Hello!".getBytes(StandardCharsets.UTF_8)))); - // 200 status would be streamed body, force to buffered - response.setBodyStreamRereadable(); - - InputStream stream = response.bodyStream(); - assertThat(stream, isA(ByteArrayInputStream.class)); - String bodyString = IOUtils.toString(stream, StandardCharsets.UTF_8); - assertThat(bodyString, equalTo("Hello!")); - - // Buffered response can be read multiple times - bodyString = IOUtils.toString(response.bodyStream(), StandardCharsets.UTF_8); - assertThat(bodyString, equalTo("Hello!")); - - response.close(); - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response is closed")); - } - - /** - * Test rereadable body stream. - * - * @throws Exception - * for failures - */ - @Test - public void tesBodyStream_rereadable() throws Exception { - Exception e; - GitHubConnectorResponse response = new CustomBodyGitHubConnectorResponse(404, - new ByteBufferBackedInputStream(ByteBuffer.wrap("Hello!".getBytes(StandardCharsets.UTF_8)))); - InputStream stream = response.bodyStream(); - assertThat(stream, isA(ByteArrayInputStream.class)); - String bodyString = IOUtils.toString(stream, StandardCharsets.UTF_8); - assertThat(bodyString, equalTo("Hello!")); - - // Buffered response can be read multiple times - bodyString = IOUtils.toString(response.bodyStream(), StandardCharsets.UTF_8); - assertThat(bodyString, equalTo("Hello!")); - - // should have no effect if already rereadable - response.setBodyStreamRereadable(); - - response.close(); - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response is closed")); - } - - /** - * Test basic body stream. - * - * @throws Exception - * for failures - */ - @Test - public void testBodyStream() throws Exception { - Exception e; - GitHubConnectorResponse response = new CustomBodyGitHubConnectorResponse(200, - new ByteBufferBackedInputStream(ByteBuffer.wrap("Hello!".getBytes(StandardCharsets.UTF_8)))); - InputStream stream = response.bodyStream(); - assertThat(stream, isA(ByteBufferBackedInputStream.class)); - String bodyString = IOUtils.toString(stream, StandardCharsets.UTF_8); - assertThat(bodyString, equalTo("Hello!")); - - // Cannot change to rereadable - e = Assert.assertThrows(RuntimeException.class, () -> response.setBodyStreamRereadable()); - assertThat(e.getMessage(), equalTo("bodyStream() already called in read-once mode")); - - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response body not rereadable")); - response.close(); - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response is closed")); - } - - /** - * Test null body stream. - * - * @throws Exception - * for failures - */ - @Test - public void testBodyStream_null() throws Exception { - Exception e; - GitHubConnectorResponse response = new CustomBodyGitHubConnectorResponse(200, null); - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response body missing, stream null")); - - // Cannot change to rereadable - e = Assert.assertThrows(RuntimeException.class, () -> response.setBodyStreamRereadable()); - assertThat(e.getMessage(), equalTo("bodyStream() already called in read-once mode")); - - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response body not rereadable")); - - response.close(); - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response is closed")); - } - - /** - * Test null rereadable body stream. - * - * @throws Exception - * for failures - */ - @Test - public void testBodyStream_null_buffered() throws Exception { - Exception e; - GitHubConnectorResponse response = new CustomBodyGitHubConnectorResponse(404, null); - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response body missing, stream null")); - // Buffered response can be read multiple times - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response body missing, stream null")); - - // force should have no effect after first read attempt - response.setBodyStreamRereadable(); - - response.close(); - e = Assert.assertThrows(IOException.class, () -> response.bodyStream()); - assertThat(e.getMessage(), equalTo("Response is closed")); - } - -} diff --git a/src/test/java/org/kohsuke/github/extras/authorization/AuthorizationTokenRefreshTest.java b/src/test/java/org/kohsuke/github/extras/authorization/AuthorizationTokenRefreshTest.java index e090b46329..00b268912b 100644 --- a/src/test/java/org/kohsuke/github/extras/authorization/AuthorizationTokenRefreshTest.java +++ b/src/test/java/org/kohsuke/github/extras/authorization/AuthorizationTokenRefreshTest.java @@ -14,19 +14,6 @@ */ public class AuthorizationTokenRefreshTest extends AbstractGitHubWireMockTest { - static class RefreshingAuthorizationProvider implements AuthorizationProvider { - private boolean used = false; - - @Override - public String getEncodedAuthorization() { - if (used) { - return "refreshed token"; - } - used = true; - return "original token"; - } - } - /** * Instantiates a new test. */ @@ -34,6 +21,16 @@ public AuthorizationTokenRefreshTest() { useDefaultGitHub = false; } + /** + * Gets the wire mock options. + * + * @return the wire mock options + */ + @Override + protected WireMockConfiguration getWireMockOptions() { + return super.getWireMockOptions().extensions(templating.newResponseTransformer()); + } + /** * Retried request should get new token when the old one expires. * @@ -67,13 +64,16 @@ public void testNotNewWhenOldOneIsStillValid() throws IOException { assertThat("Usernames match", "kohsuke".equals(kohsuke.getLogin())); } - /** - * Gets the wire mock options. - * - * @return the wire mock options - */ - @Override - protected WireMockConfiguration getWireMockOptions() { - return super.getWireMockOptions().extensions(templating.newResponseTransformer()); + static class RefreshingAuthorizationProvider implements AuthorizationProvider { + private boolean used = false; + + @Override + public String getEncodedAuthorization() { + if (used) { + return "refreshed token"; + } + used = true; + return "original token"; + } } } diff --git a/src/test/java/org/kohsuke/github/extras/authorization/JWTTokenProviderTest.java b/src/test/java/org/kohsuke/github/extras/authorization/JWTTokenProviderTest.java index 70a73fabb1..4b98cc18c5 100644 --- a/src/test/java/org/kohsuke/github/extras/authorization/JWTTokenProviderTest.java +++ b/src/test/java/org/kohsuke/github/extras/authorization/JWTTokenProviderTest.java @@ -32,15 +32,33 @@ */ public class JWTTokenProviderTest extends AbstractGHAppInstallationTest { - private static String PRIVATE_KEY_FILE_APP_2 = "/ghapi-test-app-2.private-key.pem"; - - private static String TEST_APP_ID_2 = "83009"; /** * Create default JWTTokenProviderTest instance */ public JWTTokenProviderTest() { } + private static String TEST_APP_ID_2 = "83009"; + private static String PRIVATE_KEY_FILE_APP_2 = "/ghapi-test-app-2.private-key.pem"; + + /** + * Test caching valid authorization. + * + * @throws IOException + * Signals that an I/O exception has occurred. + */ + @Test + public void testCachingValidAuthorization() throws IOException { + assertThat(jwtProvider1, instanceOf(JWTTokenProvider.class)); + JWTTokenProvider provider = (JWTTokenProvider) jwtProvider1; + + assertThat(provider.isNotValid(), is(true)); + String authorization = provider.getEncodedAuthorization(); + assertThat(provider.isNotValid(), is(false)); + String authorizationRefresh = provider.getEncodedAuthorization(); + assertThat(authorizationRefresh, sameInstance(authorization)); + } + /** * Test authorization header pattern. * @@ -65,24 +83,6 @@ public void testAuthorizationHeaderPattern() throws GeneralSecurityException, IO gh.getApp(); } - /** - * Test caching valid authorization. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @Test - public void testCachingValidAuthorization() throws IOException { - assertThat(jwtProvider1, instanceOf(JWTTokenProvider.class)); - JWTTokenProvider provider = (JWTTokenProvider) jwtProvider1; - - assertThat(provider.isNotValid(), is(true)); - String authorization = provider.getEncodedAuthorization(); - assertThat(provider.isNotValid(), is(false)); - String authorizationRefresh = provider.getEncodedAuthorization(); - assertThat(authorizationRefresh, sameInstance(authorization)); - } - /** * Test issued at skew. * diff --git a/src/test/java/org/kohsuke/github/extras/okhttp3/GitHubCachingTest.java b/src/test/java/org/kohsuke/github/extras/okhttp3/GitHubCachingTest.java index 334b7e1052..f66717f31a 100644 --- a/src/test/java/org/kohsuke/github/extras/okhttp3/GitHubCachingTest.java +++ b/src/test/java/org/kohsuke/github/extras/okhttp3/GitHubCachingTest.java @@ -19,6 +19,8 @@ import java.io.File; import java.io.IOException; +import static org.junit.Assert.fail; + // TODO: Auto-generated Javadoc /** * Test showing the behavior of OkHttpGitHubConnector cache with GitHub 404 responses. @@ -27,20 +29,27 @@ */ public class GitHubCachingTest extends AbstractGitHubWireMockTest { - private static int clientCount = 0; - - private static GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + /** + * Instantiates a new git hub caching test. + */ + public GitHubCachingTest() { + useDefaultGitHub = false; } /** The test ref name. */ String testRefName = "heads/test/content_ref_cache"; /** - * Instantiates a new git hub caching test. + * Gets the wire mock options. + * + * @return the wire mock options */ - public GitHubCachingTest() { - useDefaultGitHub = false; + @Override + protected WireMockConfiguration getWireMockOptions() { + return super.getWireMockOptions() + // Use the same data files as the 2.x test + .usingFilesUnderDirectory(baseRecordPath.replace("/okhttp3/", "/")) + .extensions(templating.newResponseTransformer()); } /** @@ -178,6 +187,8 @@ public void testCached404() throws Exception { repo.getRef(testRefName); } + private static int clientCount = 0; + private OkHttpClient createClient(boolean useCache) throws IOException { OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); @@ -194,17 +205,8 @@ private OkHttpClient createClient(boolean useCache) throws IOException { return builder.build(); } - /** - * Gets the wire mock options. - * - * @return the wire mock options - */ - @Override - protected WireMockConfiguration getWireMockOptions() { - return super.getWireMockOptions() - // Use the same data files as the 2.x test - .usingFilesUnderDirectory(baseRecordPath.replace("/okhttp3/", "/")) - .extensions(templating.newResponseTransformer()); + private static GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); } } diff --git a/src/test/java/org/kohsuke/github/extras/okhttp3/OkHttpGitHubConnectorTest.java b/src/test/java/org/kohsuke/github/extras/okhttp3/OkHttpGitHubConnectorTest.java index a204fe6e2e..d21e853bc3 100644 --- a/src/test/java/org/kohsuke/github/extras/okhttp3/OkHttpGitHubConnectorTest.java +++ b/src/test/java/org/kohsuke/github/extras/okhttp3/OkHttpGitHubConnectorTest.java @@ -45,36 +45,76 @@ */ public class OkHttpGitHubConnectorTest extends AbstractGitHubWireMockTest { - private static int defaultNetworkRequestCount = 16; + /** + * Instantiates a new ok http git hub connector test. + */ + public OkHttpGitHubConnectorTest() { + useDefaultGitHub = false; + } private static int defaultRateLimitUsed = 17; - private static int maxAgeNoneHitCount = 11; - private static int maxAgeNoneNetworkRequestCount = 5; + private static int okhttpRateLimitUsed = 17; + private static int maxAgeZeroRateLimitUsed = 7; + private static int maxAgeThreeRateLimitUsed = 7; private static int maxAgeNoneRateLimitUsed = 4; - private static int maxAgeThreeHitCount = 10; + private static int userRequestCount = 0; + + private static int defaultNetworkRequestCount = 16; + private static int okhttpNetworkRequestCount = 16; + private static int maxAgeZeroNetworkRequestCount = 16; private static int maxAgeThreeNetworkRequestCount = 9; + private static int maxAgeNoneNetworkRequestCount = 5; - private static int maxAgeThreeRateLimitUsed = 7; private static int maxAgeZeroHitCount = 10; - private static int maxAgeZeroNetworkRequestCount = 16; - private static int maxAgeZeroRateLimitUsed = 7; - private static int okhttpNetworkRequestCount = 16; + private static int maxAgeThreeHitCount = 10; + private static int maxAgeNoneHitCount = 11; - private static int okhttpRateLimitUsed = 17; - private static int userRequestCount = 0; - private static GHRepository getRepository(GitHub gitHub) throws IOException { - return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); + private GHRateLimit rateLimitBefore; + private Cache cache = null; + + /** + * Gets the wire mock options. + * + * @return the wire mock options + */ + @Override + protected WireMockConfiguration getWireMockOptions() { + return super.getWireMockOptions() + // Use the same data files as the 2.x test + .usingFilesUnderDirectory(baseRecordPath.replace("/okhttp3/OkHttpGitHubConnector", "/OkHttpConnector")) + .extensions(templating.newResponseTransformer()); } - private Cache cache = null; - private GHRateLimit rateLimitBefore; + /** + * Setup repo. + * + * @throws Exception + * the exception + */ + @Before + public void setupRepo() throws Exception { + if (mockGitHub.isUseProxy()) { + GHRepository repo = getRepository(getNonRecordingGitHub()); + repo.setDescription("Resetting"); + + // Let things settle a bit between tests when working against the live site + Thread.sleep(5000); + userRequestCount = 1; + } + } /** - * Instantiates a new ok http git hub connector test. + * Delete cache. + * + * @throws IOException + * Signals that an I/O exception has occurred. */ - public OkHttpGitHubConnectorTest() { - useDefaultGitHub = false; + @After + public void deleteCache() throws IOException { + if (cache != null) { + cache.delete(); + } } /** @@ -98,19 +138,15 @@ public void DefaultConnector() throws Exception { } /** - * Ok http connector cache max age default zero. + * Ok http connector no cache. * * @throws Exception * the exception */ @Test - public void OkHttpConnector_Cache_MaxAgeDefault_Zero() throws Exception { - // The responses were recorded from github, but the Date headers - // have been templated to make caching behavior work as expected. - // This is reasonable as long as the number of network requests matches up. - snapshotNotAllowed(); + public void OkHttpConnector_NoCache() throws Exception { - OkHttpClient client = createClient(true); + OkHttpClient client = createClient(false); OkHttpGitHubConnector connector = new OkHttpGitHubConnector(client); this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) @@ -120,12 +156,12 @@ public void OkHttpConnector_Cache_MaxAgeDefault_Zero() throws Exception { doTestActions(); // Testing behavior after change - // NOTE: max-age=0 produces the same result at uncached without added rate-limit use. + // Uncached okhttp connection gets updated correctly but at cost of rate limit assertThat(getRepository(gitHub).getDescription(), is("Tricky")); - checkRequestAndLimit(maxAgeZeroNetworkRequestCount, maxAgeZeroRateLimitUsed); + checkRequestAndLimit(okhttpNetworkRequestCount, okhttpRateLimitUsed); - assertThat("getHitCount", cache.hitCount(), is(maxAgeZeroHitCount)); + assertThat("Cache", cache, is(nullValue())); } /** @@ -194,15 +230,19 @@ public void OkHttpConnector_Cache_MaxAge_Three() throws Exception { } /** - * Ok http connector no cache. + * Ok http connector cache max age default zero. * * @throws Exception * the exception */ @Test - public void OkHttpConnector_NoCache() throws Exception { + public void OkHttpConnector_Cache_MaxAgeDefault_Zero() throws Exception { + // The responses were recorded from github, but the Date headers + // have been templated to make caching behavior work as expected. + // This is reasonable as long as the number of network requests matches up. + snapshotNotAllowed(); - OkHttpClient client = createClient(false); + OkHttpClient client = createClient(true); OkHttpGitHubConnector connector = new OkHttpGitHubConnector(client); this.gitHub = getGitHubBuilder().withEndpoint(mockGitHub.apiServer().baseUrl()) @@ -212,46 +252,15 @@ public void OkHttpConnector_NoCache() throws Exception { doTestActions(); // Testing behavior after change - // Uncached okhttp connection gets updated correctly but at cost of rate limit + // NOTE: max-age=0 produces the same result at uncached without added rate-limit use. assertThat(getRepository(gitHub).getDescription(), is("Tricky")); - checkRequestAndLimit(okhttpNetworkRequestCount, okhttpRateLimitUsed); - - assertThat("Cache", cache, is(nullValue())); - } - - /** - * Delete cache. - * - * @throws IOException - * Signals that an I/O exception has occurred. - */ - @After - public void deleteCache() throws IOException { - if (cache != null) { - cache.delete(); - } - } - - /** - * Setup repo. - * - * @throws Exception - * the exception - */ - @Before - public void setupRepo() throws Exception { - if (mockGitHub.isUseProxy()) { - GHRepository repo = getRepository(getNonRecordingGitHub()); - repo.setDescription("Resetting"); + checkRequestAndLimit(maxAgeZeroNetworkRequestCount, maxAgeZeroRateLimitUsed); - // Let things settle a bit between tests when working against the live site - Thread.sleep(5000); - userRequestCount = 1; - } + assertThat("getHitCount", cache.hitCount(), is(maxAgeZeroHitCount)); } - private void checkRequestAndLimit(int networkRequestCount, int rateLimitUsed) { + private void checkRequestAndLimit(int networkRequestCount, int rateLimitUsed) throws IOException { GHRateLimit rateLimitAfter = gitHub.lastRateLimit(); assertThat("Request Count", getRequestCount(), is(networkRequestCount + userRequestCount)); @@ -262,6 +271,10 @@ private void checkRequestAndLimit(int networkRequestCount, int rateLimitUsed) { } + private int getRequestCount() { + return mockGitHub.apiServer().countRequestsMatching(RequestPatternBuilder.allRequests().build()).getCount(); + } + private OkHttpClient createClient(boolean useCache) throws IOException { OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); @@ -310,10 +323,6 @@ private void doTestActions() throws Exception { pollForChange("Tricky"); } - private int getRequestCount() { - return mockGitHub.apiServer().countRequestsMatching(RequestPatternBuilder.allRequests().build()).getCount(); - } - private void pollForChange(String name) throws IOException, InterruptedException { getRepository(gitHub).getDescription(); Thread.sleep(500); @@ -331,17 +340,8 @@ private void pollForChange(String name) throws IOException, InterruptedException } } - /** - * Gets the wire mock options. - * - * @return the wire mock options - */ - @Override - protected WireMockConfiguration getWireMockOptions() { - return super.getWireMockOptions() - // Use the same data files as the 2.x test - .usingFilesUnderDirectory(baseRecordPath.replace("/okhttp3/OkHttpGitHubConnector", "/OkHttpConnector")) - .extensions(templating.newResponseTransformer()); + private static GHRepository getRepository(GitHub gitHub) throws IOException { + return gitHub.getOrganization("hub4j-test-org").getRepository("github-api"); } } diff --git a/src/test/java/org/kohsuke/github/internal/EnumUtilsTest.java b/src/test/java/org/kohsuke/github/internal/EnumUtilsTest.java index 88df55a576..5169e947a5 100644 --- a/src/test/java/org/kohsuke/github/internal/EnumUtilsTest.java +++ b/src/test/java/org/kohsuke/github/internal/EnumUtilsTest.java @@ -11,10 +11,6 @@ */ public class EnumUtilsTest { - private enum TestEnum { - UNKNOWN, VALUE_1, VALUE_2; - } - /** * Create default EnumUtilsTest instance */ @@ -40,4 +36,8 @@ public void testGetEnum() { assertThat(EnumUtils.getNullableEnumOrDefault(TestEnum.class, "vAlUe_2", TestEnum.UNKNOWN), equalTo(TestEnum.VALUE_2)); } + + private enum TestEnum { + VALUE_1, VALUE_2, UNKNOWN; + } } diff --git a/src/test/java/org/kohsuke/github/internal/graphql/response/GHGraphQLResponseMockTest.java b/src/test/java/org/kohsuke/github/internal/graphql/response/GHGraphQLResponseMockTest.java deleted file mode 100644 index a98870c6ec..0000000000 --- a/src/test/java/org/kohsuke/github/internal/graphql/response/GHGraphQLResponseMockTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.kohsuke.github.internal.graphql.response; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import org.junit.jupiter.api.Test; - -import java.util.List; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.is; - -/** - * Test GHGraphQLResponse's methods - */ -class GHGraphQLResponseMockTest { - - private GHGraphQLResponse convertJsonToGraphQLResponse(String json) throws JsonProcessingException { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - - ObjectReader objectReader = objectMapper.reader(); - JavaType javaType = objectReader.getTypeFactory() - .constructParametricType(GHGraphQLResponse.class, Object.class); - - return objectReader.forType(javaType).readValue(json); - } - - /** - * Test get data throws exception when response means error - * - * @throws JsonProcessingException - * Json parse exception - * - */ - @Test - void getDataFailure() throws JsonProcessingException { - String graphQLErrorResponse = "{\"data\": {\"enablePullRequestAutoMerge\": null},\"errors\": [{\"type\": " - + "\"UNPROCESSABLE\",\"path\": [\"enablePullRequestAutoMerge\"],\"locations\": [{\"line\": 2," - + "\"column\": 5}],\"message\": \"hub4j does not have a verified email, which is required to enable " - + "auto-merging.\"}]}"; - - GHGraphQLResponse response = convertJsonToGraphQLResponse(graphQLErrorResponse); - - try { - response.getData(); - } catch (RuntimeException e) { - assertThat(e.getMessage(), containsString("Response not successful, data invalid")); - } - } - - /** - * Test getErrorMessages throws exception when response means not error - * - * @throws JsonProcessingException - * Json parse exception - */ - @Test - void getErrorMessagesFailure() throws JsonProcessingException { - String graphQLSuccessResponse = "{\"data\": {\"repository\": {\"pullRequest\": {\"id\": " - + "\"PR_TEMP_GRAPHQL_ID\"}}}}"; - - GHGraphQLResponse response = convertJsonToGraphQLResponse(graphQLSuccessResponse); - - List errorMessages = response.getErrorMessages(); - - assertThat(errorMessages, is(empty())); - } - -} diff --git a/src/test/resources/no-reflect-and-serialization-list b/src/test/resources/no-reflect-and-serialization-list index 4ad893272c..e1e4fa2e0d 100644 --- a/src/test/resources/no-reflect-and-serialization-list +++ b/src/test/resources/no-reflect-and-serialization-list @@ -81,6 +81,4 @@ org.kohsuke.github.function.SupplierThrows org.kohsuke.github.internal.DefaultGitHubConnector org.kohsuke.github.internal.EnumUtils org.kohsuke.github.internal.Previews -org.kohsuke.github.EnterpriseManagedSupport -org.kohsuke.github.GHAutolinkBuilder -org.kohsuke.github.GHRepositoryForkBuilder \ No newline at end of file +org.kohsuke.github.EnterpriseManagedSupport \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/__files/27-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/__files/27-notifications.json deleted file mode 100644 index 9527e46df8..0000000000 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/__files/27-notifications.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "message": "Unable to parse If-Modified-Since request header. Please make sure value is in an acceptable format.", - "documentation_url": "https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user", - "status": "422" -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/10-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/10-notifications.json index 7304188eb8..b16ad3007a 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/10-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/10-notifications.json @@ -2,7 +2,7 @@ "id": "a979348d-c6be-4cb7-8877-7c42a6f013ae", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=9", + "url": "/notifications?all=true&page=9", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F628:BFE1F0:5DB3A14D", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "a979348d-c6be-4cb7-8877-7c42a6f013ae", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/11-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/11-notifications.json index c02ba6ccd0..85f3b573c0 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/11-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/11-notifications.json @@ -2,7 +2,7 @@ "id": "89714ed3-235b-4914-86a8-44ad66d59f30", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=10", + "url": "/notifications?all=true&page=10", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F646:BFE217:5DB3A14D", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "89714ed3-235b-4914-86a8-44ad66d59f30", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/12-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/12-notifications.json index 84c0a42873..8907d54645 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/12-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/12-notifications.json @@ -2,7 +2,7 @@ "id": "2b718339-36d3-4c6b-9484-79cdd79a79e4", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=11", + "url": "/notifications?all=true&page=11", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F657:BFE22B:5DB3A14D", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "2b718339-36d3-4c6b-9484-79cdd79a79e4", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/13-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/13-notifications.json index 3481d18741..e6b46f7ecb 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/13-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/13-notifications.json @@ -2,7 +2,7 @@ "id": "989db4b3-8dde-4065-b4ef-6a2d90a2753a", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=12", + "url": "/notifications?all=true&page=12", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F661:BFE238:5DB3A14E", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "989db4b3-8dde-4065-b4ef-6a2d90a2753a", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/14-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/14-notifications.json index 08f647fcad..bd27626d4e 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/14-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/14-notifications.json @@ -2,7 +2,7 @@ "id": "50b907ef-a983-4cc9-bfd2-e2ba76eae729", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=13", + "url": "/notifications?all=true&page=13", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F66D:BFE242:5DB3A14E", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "50b907ef-a983-4cc9-bfd2-e2ba76eae729", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/15-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/15-notifications.json index 139228796a..2086a8fdbd 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/15-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/15-notifications.json @@ -2,7 +2,7 @@ "id": "f2648b73-4af1-4be3-a2a4-9edc712c5d59", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=14", + "url": "/notifications?all=true&page=14", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F679:BFE254:5DB3A14E", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "f2648b73-4af1-4be3-a2a4-9edc712c5d59", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/16-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/16-notifications.json index 596d062a2b..60d836dec6 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/16-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/16-notifications.json @@ -2,7 +2,7 @@ "id": "ee5a6c9f-da3a-47e7-a393-b403e82ae5d9", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=15", + "url": "/notifications?all=true&page=15", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F689:BFE266:5DB3A14E", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "ee5a6c9f-da3a-47e7-a393-b403e82ae5d9", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/17-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/17-notifications.json index 2b3fcaa99d..25cf77ff48 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/17-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/17-notifications.json @@ -2,7 +2,7 @@ "id": "a41aeecf-7097-4ac6-b857-ab14797afe0a", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=16", + "url": "/notifications?all=true&page=16", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F69E:BFE27A:5DB3A14F", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "a41aeecf-7097-4ac6-b857-ab14797afe0a", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/18-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/18-notifications.json index 3e04973df2..42c582816a 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/18-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/18-notifications.json @@ -2,7 +2,7 @@ "id": "e1d519f7-9bd2-4fcd-a288-2391944ec7ca", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=17", + "url": "/notifications?all=true&page=17", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F6B4:BFE291:5DB3A14F", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "e1d519f7-9bd2-4fcd-a288-2391944ec7ca", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/19-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/19-notifications.json index a2bc722b01..5bc7d00622 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/19-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/19-notifications.json @@ -2,7 +2,7 @@ "id": "1b694852-8043-418c-a76e-39370f22db96", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=18", + "url": "/notifications?all=true&page=18", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F6CA:BFE2B2:5DB3A14F", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "1b694852-8043-418c-a76e-39370f22db96", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/2-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/2-notifications.json index 46240a1d92..1b160a9c8b 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/2-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/2-notifications.json @@ -2,7 +2,7 @@ "id": "d85867b0-1efe-43f5-bdf4-1b9aef03ef55", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z", + "url": "/notifications?all=true", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F5C2:BFE16E:5DB3A14B", - "Link": "; rel=\"next\", ; rel=\"last\"" + "Link": "; rel=\"next\", ; rel=\"last\"" } }, "uuid": "d85867b0-1efe-43f5-bdf4-1b9aef03ef55", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/20-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/20-notifications.json index 5d4bc6c3df..d99f71b368 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/20-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/20-notifications.json @@ -2,7 +2,7 @@ "id": "48908278-ce2f-4cec-8662-6f4ca3d81226", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=19", + "url": "/notifications?all=true&page=19", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F6E4:BFE2D4:5DB3A150", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "48908278-ce2f-4cec-8662-6f4ca3d81226", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/21-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/21-notifications.json index 6e011fce6f..0d01191175 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/21-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/21-notifications.json @@ -2,7 +2,7 @@ "id": "42be6527-0570-4353-b42f-d0cae80258e3", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=20", + "url": "/notifications?all=true&page=20", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F70C:BFE300:5DB3A150", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "42be6527-0570-4353-b42f-d0cae80258e3", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/22-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/22-notifications.json index bcaf874f82..0578186986 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/22-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/22-notifications.json @@ -2,7 +2,7 @@ "id": "5720c49c-c69b-495b-b7e6-b885d88c10b1", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=21", + "url": "/notifications?all=true&page=21", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F71C:BFE311:5DB3A150", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "5720c49c-c69b-495b-b7e6-b885d88c10b1", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/23-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/23-notifications.json index 11e575c017..28bdd8d595 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/23-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/23-notifications.json @@ -2,7 +2,7 @@ "id": "045c369a-0818-455a-afe1-3ae9ec919af2", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=22", + "url": "/notifications?all=true&page=22", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F731:BFE31F:5DB3A151", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "045c369a-0818-455a-afe1-3ae9ec919af2", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/24-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/24-notifications.json index 450bd8797d..fb5ac17e0f 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/24-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/24-notifications.json @@ -2,7 +2,7 @@ "id": "bfc7733f-6dff-4675-81e9-926103c40b83", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=23", + "url": "/notifications?all=true&page=23", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F73A:BFE332:5DB3A151", - "Link": "; rel=\"prev\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"first\"" } }, "uuid": "bfc7733f-6dff-4675-81e9-926103c40b83", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/26-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/26-notifications.json index a120a83569..5a7378d124 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/26-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/26-notifications.json @@ -40,7 +40,8 @@ "X-XSS-Protection": "1; mode=block", "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", - "X-GitHub-Request-Id": "CB13:833E:A1F759:BFE352:5DB3A151" + "X-GitHub-Request-Id": "CB13:833E:A1F759:BFE352:5DB3A151", + "Link": "; rel=\"next\", ; rel=\"last\"" } }, "uuid": "ac22e3e2-f0d3-4ff1-af23-23e9c79c725c", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/27-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/27-notifications.json deleted file mode 100644 index f6c602f01a..0000000000 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/27-notifications.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "ac22e3e2-f0d3-4ff1-af23-23e9c7915874", - "name": "notifications", - "request": { - "url": "/notifications", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - }, - "If-Modified-Since":{ - "equalTo": "null" - } - } - }, - "response": { - "status": 422, - "bodyFileName": "27-notifications.json", - "headers": { - "Date": "Wed, 20 Nov 2024 13:55:23 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "repo", - "X-Accepted-OAuth-Scopes": "notifications, repo", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4992", - "X-RateLimit-Reset": "1732111985", - "X-RateLimit-Used": "8", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "052F:2E353B:3FE0C:42EBB:673DEA4B" - } - }, - "uuid": "ac22e3e2-f0d3-4ff1-af23-23e9c7915874", - "persistent": true, - "insertionIndex": 26 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/3-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/3-notifications.json index 963a173b9a..686668959e 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/3-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/3-notifications.json @@ -2,7 +2,7 @@ "id": "d9617266-1ca6-44b2-b495-52c1f3be4b91", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=2", + "url": "/notifications?all=true&page=2", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F5D0:BFE187:5DB3A14B", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "d9617266-1ca6-44b2-b495-52c1f3be4b91", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/4-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/4-notifications.json index bfd2be216d..590392dc5a 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/4-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/4-notifications.json @@ -2,7 +2,7 @@ "id": "6dea5253-3aa2-4484-b97a-effcad5c6ebd", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=3", + "url": "/notifications?all=true&page=3", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F5DC:BFE198:5DB3A14B", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "6dea5253-3aa2-4484-b97a-effcad5c6ebd", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/5-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/5-notifications.json index 4f60ae1eb3..a12e55a622 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/5-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/5-notifications.json @@ -2,7 +2,7 @@ "id": "a8e9449d-b78c-4e46-801e-59fc459920d3", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=4", + "url": "/notifications?all=true&page=4", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F5E4:BFE1A3:5DB3A14C", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "a8e9449d-b78c-4e46-801e-59fc459920d3", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/6-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/6-notifications.json index c6b6c09cb9..4c448dd5ba 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/6-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/6-notifications.json @@ -2,7 +2,7 @@ "id": "2658e99a-6619-4b0b-b70f-814a0841839e", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=5", + "url": "/notifications?all=true&page=5", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F5F0:BFE1B4:5DB3A14C", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "2658e99a-6619-4b0b-b70f-814a0841839e", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/7-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/7-notifications.json index 7f78aac737..038b30ff7b 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/7-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/7-notifications.json @@ -2,7 +2,7 @@ "id": "f2524684-5156-4db6-97fa-10dedac5f779", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=6", + "url": "/notifications?all=true&page=6", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F5FD:BFE1C1:5DB3A14C", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "f2524684-5156-4db6-97fa-10dedac5f779", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/8-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/8-notifications.json index 6b084811db..4a245443ff 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/8-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/8-notifications.json @@ -2,7 +2,7 @@ "id": "9437189d-2f1b-47de-898d-66fde88ef05b", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=7", + "url": "/notifications?all=true&page=7", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F60A:BFE1CD:5DB3A14C", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "9437189d-2f1b-47de-898d-66fde88ef05b", diff --git a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/9-notifications.json b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/9-notifications.json index b2c14fe37e..3a479236b2 100644 --- a/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/9-notifications.json +++ b/src/test/resources/org/kohsuke/github/AppTest/wiremock/notifications/mappings/9-notifications.json @@ -2,7 +2,7 @@ "id": "1de52522-e900-4b19-90cd-758573c2349a", "name": "notifications", "request": { - "url": "/notifications?all=true&since=1970-01-01T00%3A00%3A00Z&page=8", + "url": "/notifications?all=true&page=8", "method": "GET", "headers": { "Accept": { @@ -41,7 +41,7 @@ "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "Content-Security-Policy": "default-src 'none'", "X-GitHub-Request-Id": "CB13:833E:A1F612:BFE1D9:5DB3A14C", - "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" + "Link": "; rel=\"prev\", ; rel=\"next\", ; rel=\"last\", ; rel=\"first\"" } }, "uuid": "1de52522-e900-4b19-90cd-758573c2349a", diff --git a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/__files/1-app.json b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/__files/1-app.json deleted file mode 100644 index 6eddba3601..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/__files/1-app.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "id": 986532, - "client_id": "Iv23liTxF5NAu46u9qto", - "slug": "anuj-github-app", - "node_id": "A_kwDOB7K2ac4ADw2k", - "owner": { - "login": "kaladinstormblessed", - "id": 129152617, - "node_id": "U_kgDOB7K2aQ", - "avatar_url": "https://avatars.githubusercontent.com/u/129152617?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/kaladinstormblessed", - "html_url": "https://github.com/kaladinstormblessed", - "followers_url": "https://api.github.com/users/kaladinstormblessed/followers", - "following_url": "https://api.github.com/users/kaladinstormblessed/following{/other_user}", - "gists_url": "https://api.github.com/users/kaladinstormblessed/gists{/gist_id}", - "starred_url": "https://api.github.com/users/kaladinstormblessed/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/kaladinstormblessed/subscriptions", - "organizations_url": "https://api.github.com/users/kaladinstormblessed/orgs", - "repos_url": "https://api.github.com/users/kaladinstormblessed/repos", - "events_url": "https://api.github.com/users/kaladinstormblessed/events{/privacy}", - "received_events_url": "https://api.github.com/users/kaladinstormblessed/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "name": "anuj-github-app", - "description": "", - "external_url": "https://cloud.cloud", - "html_url": "https://github.com/apps/anuj-github-app", - "created_at": "2024-09-03T07:14:38Z", - "updated_at": "2025-01-17T10:52:47Z", - "permissions": { - "administration": "write", - "contents": "write", - "members": "read", - "metadata": "read", - "pull_requests": "read" - }, - "events": [], - "installations_count": 6 -} diff --git a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/__files/2-app_installation-requests.json b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/__files/2-app_installation-requests.json deleted file mode 100644 index 46c2ad4c16..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/__files/2-app_installation-requests.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "id": 1037204, - "node_id": "MDMwOkludGVncmF0aW9uSW5zdGFsbGF0aW9uUmVxdWVzdDEwMzcyMDQ=", - "account": { - "login": "approval-test", - "id": 195438329, - "node_id": "O_kgDOC6Ym-Q", - "avatar_url": "https://avatars.githubusercontent.com/u/195438329?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/approval-test", - "html_url": "https://github.com/approval-test", - "followers_url": "https://api.github.com/users/approval-test/followers", - "following_url": "https://api.github.com/users/approval-test/following{/other_user}", - "gists_url": "https://api.github.com/users/approval-test/gists{/gist_id}", - "starred_url": "https://api.github.com/users/approval-test/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/approval-test/subscriptions", - "organizations_url": "https://api.github.com/users/approval-test/orgs", - "repos_url": "https://api.github.com/users/approval-test/repos", - "events_url": "https://api.github.com/users/approval-test/events{/privacy}", - "received_events_url": "https://api.github.com/users/approval-test/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "requester": { - "login": "kaladinstormblessed2", - "id": 195437694, - "node_id": "U_kgDOC6Ykfg", - "avatar_url": "https://avatars.githubusercontent.com/u/195437694?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/kaladinstormblessed2", - "html_url": "https://github.com/kaladinstormblessed2", - "followers_url": "https://api.github.com/users/kaladinstormblessed2/followers", - "following_url": "https://api.github.com/users/kaladinstormblessed2/following{/other_user}", - "gists_url": "https://api.github.com/users/kaladinstormblessed2/gists{/gist_id}", - "starred_url": "https://api.github.com/users/kaladinstormblessed2/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/kaladinstormblessed2/subscriptions", - "organizations_url": "https://api.github.com/users/kaladinstormblessed2/orgs", - "repos_url": "https://api.github.com/users/kaladinstormblessed2/repos", - "events_url": "https://api.github.com/users/kaladinstormblessed2/events{/privacy}", - "received_events_url": "https://api.github.com/users/kaladinstormblessed2/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "created_at": "2025-01-17T15:50:51Z" - } -] diff --git a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/mappings/1-app.json b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/mappings/1-app.json deleted file mode 100644 index 24036fcca0..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/mappings/1-app.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "id": "7dd11376-7827-4472-9b35-d129d432687e", - "name": "app", - "request": { - "url": "/app", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-app.json", - "headers": { - "Date": "Fri, 17 Jan 2025 17:53:40 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "public, max-age=60, s-maxage=60", - "Vary": "Accept,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"2ae03ff428b2f6f2651437f7bbb52bcc5aa4fd43ec20540006591c05a6c4de48\"", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "C286:10C02C:61556D:734A43:678A9923" - } - }, - "uuid": "7dd11376-7827-4472-9b35-d129d432687e", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/mappings/2-app_installation-requests.json b/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/mappings/2-app_installation-requests.json deleted file mode 100644 index 51f4a3a9ec..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAppTest/wiremock/listInstallationRequests/mappings/2-app_installation-requests.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "id": "2e6e47a0-0341-45c9-87f6-eda0865764d7", - "name": "app_installation-requests", - "request": { - "url": "/app/installation-requests", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-app_installation-requests.json", - "headers": { - "Date": "Fri, 17 Jan 2025 17:53:40 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "public, max-age=60, s-maxage=60", - "Vary": "Accept,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"1030c589d5482f2436758d79218af5ab17bd8b28c5b92792fe383357cae28d39\"", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "C287:E5098:509DB7:5CBEB7:678A9924" - } - }, - "uuid": "2e6e47a0-0341-45c9-87f6-eda0865764d7", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/__files/1-user.json deleted file mode 100644 index 0764c5a936..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": null, - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 7, - "public_gists": 0, - "followers": 3, - "following": 8, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-11-27T04:01:41Z", - "private_gists": 0, - "total_private_repos": 3, - "owned_private_repos": 3, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/__files/2-r_a_github-api-test.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/__files/2-r_a_github-api-test.json deleted file mode 100644 index 00da15691e..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/__files/2-r_a_github-api-test.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "id": 895799232, - "node_id": "R_kgDONWTPwA", - "name": "github-api-test", - "full_name": "Alaurant/github-api-test", - "private": true, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/github-api-test", - "description": null, - "fork": false, - "url": "https://api.github.com/repos/Alaurant/github-api-test", - "forks_url": "https://api.github.com/repos/Alaurant/github-api-test/forks", - "keys_url": "https://api.github.com/repos/Alaurant/github-api-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/github-api-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/github-api-test/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/github-api-test/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/github-api-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/github-api-test/events", - "assignees_url": "https://api.github.com/repos/Alaurant/github-api-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/github-api-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/github-api-test/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/github-api-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/github-api-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/github-api-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/github-api-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/github-api-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/github-api-test/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/github-api-test/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/github-api-test/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/github-api-test/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/github-api-test/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/github-api-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/github-api-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/github-api-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/github-api-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/github-api-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/github-api-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/github-api-test/merges", - "archive_url": "https://api.github.com/repos/Alaurant/github-api-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/github-api-test/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/github-api-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/github-api-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/github-api-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/github-api-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/github-api-test/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/github-api-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/github-api-test/deployments", - "created_at": "2024-11-28T23:44:54Z", - "updated_at": "2024-11-28T23:44:55Z", - "pushed_at": "2024-11-28T23:44:55Z", - "git_url": "git://github.com/Alaurant/github-api-test.git", - "ssh_url": "git@github.com:Alaurant/github-api-test.git", - "clone_url": "https://github.com/Alaurant/github-api-test.git", - "svn_url": "https://github.com/Alaurant/github-api-test", - "homepage": null, - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "private", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "AJ7BLWEW6YP5EUIYTPGKLMDHJ6O5M", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "network_count": 0, - "subscribers_count": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/1-user.json deleted file mode 100644 index dcaa3400f1..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "5efad309-8a6e-4bea-b5d3-f558468cde2f", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:58 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"8bdc3eaf7312491c8eb245323f2eb3004212814ef5f8184104effa4b32f6b27c\"", - "Last-Modified": "Wed, 27 Nov 2024 04:01:41 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4964", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "36", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB4B:259AD1:AD6A0A:CCA3BA:674F9CA9" - } - }, - "uuid": "5efad309-8a6e-4bea-b5d3-f558468cde2f", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/2-r_a_github-api-test.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/2-r_a_github-api-test.json deleted file mode 100644 index b3799cfac2..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/2-r_a_github-api-test.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "7b4379d6-4382-4589-a8de-6c179a3b878e", - "name": "repos_alaurant_github-api-test", - "request": { - "url": "/repos/Alaurant/github-api-test", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_a_github-api-test.json", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:58 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"94ad6f4d71086bda8c2640d1ba979adc705c9465218c4ca1e55dc20011962ee7\"", - "Last-Modified": "Thu, 28 Nov 2024 23:44:55 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4962", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "38", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB4F:261CA8:B9F4DA:D92EA2:674F9CAA" - } - }, - "uuid": "7b4379d6-4382-4589-a8de-6c179a3b878e", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/3-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/3-r_a_g_autolinks.json deleted file mode 100644 index 882605d3e0..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/3-r_a_g_autolinks.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "id": "72c0b399-ca4c-4934-bb37-204fb2eee65c", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"key_prefix\":\"EXAMPLE-\",\"url_template\":\"https://example.com/TICKET?q=\",\"is_alphanumeric\":true}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 201, - "body": "{\"id\":6214215,\"key_prefix\":\"EXAMPLE-\",\"url_template\":\"https://example.com/TICKET?q=\",\"is_alphanumeric\":true}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:59 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"5957fc62ce793c3c3f204807841c0322d186ec5693b11e746a2a773ff4814345\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4961", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "39", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB50:25FB34:AFAC50:CEE61E:674F9CAB" - } - }, - "uuid": "72c0b399-ca4c-4934-bb37-204fb2eee65c", - "persistent": true, - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/4-r_a_g_autolinks_6214215.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/4-r_a_g_autolinks_6214215.json deleted file mode 100644 index e3e2b0ee75..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/4-r_a_g_autolinks_6214215.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "e6f3b690-7bba-4fca-af09-bb9c36c226c2", - "name": "repos_alaurant_github-api-test_autolinks_6214215", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214215", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Wed, 04 Dec 2024 00:05:00 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4960", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "40", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "AB54:25C9E5:B594DE:D4CE98:674F9CAC" - } - }, - "uuid": "e6f3b690-7bba-4fca-af09-bb9c36c226c2", - "persistent": true, - "insertionIndex": 4 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/5-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/5-r_a_g_autolinks.json deleted file mode 100644 index 3205f0a148..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testCreateAutolink/mappings/5-r_a_g_autolinks.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "4e99e7cf-51c0-42eb-aac3-11c71370da7d", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "body": "[]", - "headers": { - "Date": "Wed, 04 Dec 2024 00:05:00 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"5b744729737bd28d14aeb327919c263d8af99640a7701726d7b2320a638b5c76\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4959", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "41", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB58:2616CE:B40D89:D3475B:674F9CAC" - } - }, - "uuid": "4e99e7cf-51c0-42eb-aac3-11c71370da7d", - "persistent": true, - "insertionIndex": 5 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/__files/1-user.json deleted file mode 100644 index 0764c5a936..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": null, - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 7, - "public_gists": 0, - "followers": 3, - "following": 8, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-11-27T04:01:41Z", - "private_gists": 0, - "total_private_repos": 3, - "owned_private_repos": 3, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/__files/2-r_a_github-api-test.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/__files/2-r_a_github-api-test.json deleted file mode 100644 index f105aebb35..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/__files/2-r_a_github-api-test.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "id": 895799232, - "node_id": "R_kgDONWTPwA", - "name": "github-api-test", - "full_name": "Alaurant/github-api-test", - "private": true, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/github-api-test", - "description": null, - "fork": false, - "url": "https://api.github.com/repos/Alaurant/github-api-test", - "forks_url": "https://api.github.com/repos/Alaurant/github-api-test/forks", - "keys_url": "https://api.github.com/repos/Alaurant/github-api-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/github-api-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/github-api-test/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/github-api-test/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/github-api-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/github-api-test/events", - "assignees_url": "https://api.github.com/repos/Alaurant/github-api-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/github-api-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/github-api-test/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/github-api-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/github-api-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/github-api-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/github-api-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/github-api-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/github-api-test/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/github-api-test/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/github-api-test/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/github-api-test/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/github-api-test/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/github-api-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/github-api-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/github-api-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/github-api-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/github-api-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/github-api-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/github-api-test/merges", - "archive_url": "https://api.github.com/repos/Alaurant/github-api-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/github-api-test/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/github-api-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/github-api-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/github-api-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/github-api-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/github-api-test/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/github-api-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/github-api-test/deployments", - "created_at": "2024-11-28T23:44:54Z", - "updated_at": "2024-11-28T23:44:55Z", - "pushed_at": "2024-11-28T23:44:55Z", - "git_url": "git://github.com/Alaurant/github-api-test.git", - "ssh_url": "git@github.com:Alaurant/github-api-test.git", - "clone_url": "https://github.com/Alaurant/github-api-test.git", - "svn_url": "https://github.com/Alaurant/github-api-test", - "homepage": null, - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "private", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "AJ7BLWHAAPA4X3QOA36CYTLHJ6O4S", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "network_count": 0, - "subscribers_count": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/1-user.json deleted file mode 100644 index c37d3842de..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "cb401d70-c07b-4a80-9333-fd2598ce4873", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:44 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"8bdc3eaf7312491c8eb245323f2eb3004212814ef5f8184104effa4b32f6b27c\"", - "Last-Modified": "Wed, 27 Nov 2024 04:01:41 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4991", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "9", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AAFC:32381D:19A4CC:1E52E3:674F9C9C" - } - }, - "uuid": "cb401d70-c07b-4a80-9333-fd2598ce4873", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/2-r_a_github-api-test.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/2-r_a_github-api-test.json deleted file mode 100644 index c9bb698e1c..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/2-r_a_github-api-test.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "b4bf2f34-49d5-4aae-9962-b72cc46196c9", - "name": "repos_alaurant_github-api-test", - "request": { - "url": "/repos/Alaurant/github-api-test", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_a_github-api-test.json", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:45 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"94ad6f4d71086bda8c2640d1ba979adc705c9465218c4ca1e55dc20011962ee7\"", - "Last-Modified": "Thu, 28 Nov 2024 23:44:55 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4989", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "11", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB01:275BE1:A9865C:C65840:674F9C9D" - } - }, - "uuid": "b4bf2f34-49d5-4aae-9962-b72cc46196c9", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/3-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/3-r_a_g_autolinks.json deleted file mode 100644 index d09a8054a3..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/3-r_a_g_autolinks.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "id": "9a5172dd-9af1-4543-9140-8ca5aeaa4aaa", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"key_prefix\":\"DELETE-\",\"url_template\":\"https://example.com/delete/\",\"is_alphanumeric\":true}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 201, - "body": "{\"id\":6214199,\"key_prefix\":\"DELETE-\",\"url_template\":\"https://example.com/delete/\",\"is_alphanumeric\":true}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:45 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"a956fdb6994525df51a1d05464cca2bbfcfddd6b16580a60ebed7bee5c481b1c\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4988", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "12", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB05:25FB34:AFA666:CEDF6C:674F9C9D" - } - }, - "uuid": "9a5172dd-9af1-4543-9140-8ca5aeaa4aaa", - "persistent": true, - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/4-r_a_g_autolinks_6214199.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/4-r_a_g_autolinks_6214199.json deleted file mode 100644 index 6a7c9a740c..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/4-r_a_g_autolinks_6214199.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "cb5eb0d7-aa5f-4dec-8e47-8443c7b5eb2b", - "name": "repos_alaurant_github-api-test_autolinks_6214199", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214199", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:46 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4987", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "13", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "AB06:25DAE6:BD28AF:DC61D9:674F9C9E" - } - }, - "uuid": "cb5eb0d7-aa5f-4dec-8e47-8443c7b5eb2b", - "persistent": true, - "insertionIndex": 4 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/5-r_a_g_autolinks_6214199.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/5-r_a_g_autolinks_6214199.json deleted file mode 100644 index 5f8cdf41c6..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/5-r_a_g_autolinks_6214199.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "id": "bf5f8e71-e7c3-4fd9-a76e-8dcda49d68f0", - "name": "repos_alaurant_github-api-test_autolinks_6214199", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214199", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 404, - "body": "{\"message\":\"Not Found\",\"documentation_url\":\"https://docs.github.com/rest/repos/autolinks#get-an-autolink-reference-of-a-repository\",\"status\":\"404\"}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:46 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4986", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "14", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "AB07:25A8FF:B72F38:D66845:674F9C9E" - } - }, - "uuid": "bf5f8e71-e7c3-4fd9-a76e-8dcda49d68f0", - "persistent": true, - "insertionIndex": 5 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/6-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/6-r_a_g_autolinks.json deleted file mode 100644 index a11816818d..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/6-r_a_g_autolinks.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "id": "c5607014-5b7d-4cf5-9970-c1c5751cdf9c", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"key_prefix\":\"DELETED-\",\"url_template\":\"https://example.com/delete2/\",\"is_alphanumeric\":true}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 201, - "body": "{\"id\":6214204,\"key_prefix\":\"DELETED-\",\"url_template\":\"https://example.com/delete2/\",\"is_alphanumeric\":true}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:47 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"b344c6f9525e0a7606c9736c32b24c4bb94a746a58a0918a467d874462159497\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4985", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "15", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB0B:2377CB:ADCDF0:CBC78F:674F9C9F" - } - }, - "uuid": "c5607014-5b7d-4cf5-9970-c1c5751cdf9c", - "persistent": true, - "insertionIndex": 6 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/7-r_a_g_autolinks_6214204.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/7-r_a_g_autolinks_6214204.json deleted file mode 100644 index 5e7e325c90..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/7-r_a_g_autolinks_6214204.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "82bde32d-073f-4740-9cca-06e6ad4ca563", - "name": "repos_alaurant_github-api-test_autolinks_6214204", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214204", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:47 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4984", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "16", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "AB0C:321638:1E70D8:241378:674F9C9F" - } - }, - "uuid": "82bde32d-073f-4740-9cca-06e6ad4ca563", - "persistent": true, - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/8-r_a_g_autolinks_6214204.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/8-r_a_g_autolinks_6214204.json deleted file mode 100644 index d8e8b74f51..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/8-r_a_g_autolinks_6214204.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "id": "f41b31b6-2e5d-48f9-881b-0f96caab4c70", - "name": "repos_alaurant_github-api-test_autolinks_6214204", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214204", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 404, - "body": "{\"message\":\"Not Found\",\"documentation_url\":\"https://docs.github.com/rest/repos/autolinks#get-an-autolink-reference-of-a-repository\",\"status\":\"404\"}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:48 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4983", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "17", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "AB10:275BE1:A987C7:C659CB:674F9CA0" - } - }, - "uuid": "f41b31b6-2e5d-48f9-881b-0f96caab4c70", - "persistent": true, - "insertionIndex": 8 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/9-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/9-r_a_g_autolinks.json deleted file mode 100644 index 84c8a5d76a..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testDeleteAutolink/mappings/9-r_a_g_autolinks.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "dd326434-5694-4484-80e4-d2a63d84daf0", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "body": "[]", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:49 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"5b744729737bd28d14aeb327919c263d8af99640a7701726d7b2320a638b5c76\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4982", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "18", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB11:25E009:B3D920:D3125C:674F9CA0" - } - }, - "uuid": "dd326434-5694-4484-80e4-d2a63d84daf0", - "persistent": true, - "insertionIndex": 9 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/__files/1-user.json deleted file mode 100644 index 0764c5a936..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": null, - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 7, - "public_gists": 0, - "followers": 3, - "following": 8, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-11-27T04:01:41Z", - "private_gists": 0, - "total_private_repos": 3, - "owned_private_repos": 3, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/__files/2-r_a_github-api-test.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/__files/2-r_a_github-api-test.json deleted file mode 100644 index aea5d9d6e3..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/__files/2-r_a_github-api-test.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "id": 895799232, - "node_id": "R_kgDONWTPwA", - "name": "github-api-test", - "full_name": "Alaurant/github-api-test", - "private": true, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/github-api-test", - "description": null, - "fork": false, - "url": "https://api.github.com/repos/Alaurant/github-api-test", - "forks_url": "https://api.github.com/repos/Alaurant/github-api-test/forks", - "keys_url": "https://api.github.com/repos/Alaurant/github-api-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/github-api-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/github-api-test/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/github-api-test/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/github-api-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/github-api-test/events", - "assignees_url": "https://api.github.com/repos/Alaurant/github-api-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/github-api-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/github-api-test/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/github-api-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/github-api-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/github-api-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/github-api-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/github-api-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/github-api-test/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/github-api-test/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/github-api-test/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/github-api-test/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/github-api-test/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/github-api-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/github-api-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/github-api-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/github-api-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/github-api-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/github-api-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/github-api-test/merges", - "archive_url": "https://api.github.com/repos/Alaurant/github-api-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/github-api-test/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/github-api-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/github-api-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/github-api-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/github-api-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/github-api-test/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/github-api-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/github-api-test/deployments", - "created_at": "2024-11-28T23:44:54Z", - "updated_at": "2024-11-28T23:44:55Z", - "pushed_at": "2024-11-28T23:44:55Z", - "git_url": "git://github.com/Alaurant/github-api-test.git", - "ssh_url": "git@github.com:Alaurant/github-api-test.git", - "clone_url": "https://github.com/Alaurant/github-api-test.git", - "svn_url": "https://github.com/Alaurant/github-api-test", - "homepage": null, - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "private", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "AJ7BLWDDUCRCEJ6FDF6I2MDHJ6O44", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "network_count": 0, - "subscribers_count": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/1-user.json deleted file mode 100644 index 27b9001e4c..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "e37bea15-a992-490d-abd4-9b62de05c88e", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:49 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"8bdc3eaf7312491c8eb245323f2eb3004212814ef5f8184104effa4b32f6b27c\"", - "Last-Modified": "Wed, 27 Nov 2024 04:01:41 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4981", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "19", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB1C:2616CE:B40940:D3426D:674F9CA1" - } - }, - "uuid": "e37bea15-a992-490d-abd4-9b62de05c88e", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/2-r_a_github-api-test.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/2-r_a_github-api-test.json deleted file mode 100644 index 71b82fd4e4..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/2-r_a_github-api-test.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "6e30ba43-5316-46d1-9b80-53c527a53846", - "name": "repos_alaurant_github-api-test", - "request": { - "url": "/repos/Alaurant/github-api-test", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_a_github-api-test.json", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:50 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"94ad6f4d71086bda8c2640d1ba979adc705c9465218c4ca1e55dc20011962ee7\"", - "Last-Modified": "Thu, 28 Nov 2024 23:44:55 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4979", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "21", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB1D:32381D:19A7EC:1E5668:674F9CA2" - } - }, - "uuid": "6e30ba43-5316-46d1-9b80-53c527a53846", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/3-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/3-r_a_g_autolinks.json deleted file mode 100644 index 20ae14a08b..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/3-r_a_g_autolinks.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "bf0df31e-be26-4067-9a91-8f4c1e918c1c", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "body": "[]", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:51 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"5b744729737bd28d14aeb327919c263d8af99640a7701726d7b2320a638b5c76\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4978", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "22", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB21:253D9C:B16E05:D0A746:674F9CA3" - } - }, - "uuid": "bf0df31e-be26-4067-9a91-8f4c1e918c1c", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-github-api-test-autolinks", - "requiredScenarioState": "Started", - "newScenarioState": "scenario-1-repos-Alaurant-github-api-test-autolinks-2", - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/4-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/4-r_a_g_autolinks.json deleted file mode 100644 index c5bda9edcc..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/4-r_a_g_autolinks.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "id": "1c15b670-f893-4111-8f40-7e6843b3f3de", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"key_prefix\":\"LIST-\",\"url_template\":\"https://example.com/list1/\",\"is_alphanumeric\":true}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 201, - "body": "{\"id\":6214208,\"key_prefix\":\"LIST-\",\"url_template\":\"https://example.com/list1/\",\"is_alphanumeric\":true}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:51 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"c9b6db3f807e7bc4bb09f6a2cff12454fad030e7b1bf5c73df256d1203c86438\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4977", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "23", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB22:261CA8:B9F17C:D92AD4:674F9CA3" - } - }, - "uuid": "1c15b670-f893-4111-8f40-7e6843b3f3de", - "persistent": true, - "insertionIndex": 4 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/5-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/5-r_a_g_autolinks.json deleted file mode 100644 index 0cc310c4be..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/5-r_a_g_autolinks.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "id": "7b65f4bc-bc7a-4fd9-92dd-9b0685cc61cd", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"key_prefix\":\"LISTED-\",\"url_template\":\"https://example.com/list2/\",\"is_alphanumeric\":false}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 201, - "body": "{\"id\":6214209,\"key_prefix\":\"LISTED-\",\"url_template\":\"https://example.com/list2/\",\"is_alphanumeric\":false}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:52 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"afdd2654330781c9949511c99bff15109b2730f99b857072c555012912bbcd8b\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4976", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "24", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB26:25CB59:B00C2A:CF4583:674F9CA3" - } - }, - "uuid": "7b65f4bc-bc7a-4fd9-92dd-9b0685cc61cd", - "persistent": true, - "insertionIndex": 5 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/6-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/6-r_a_g_autolinks.json deleted file mode 100644 index f122ac898e..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/6-r_a_g_autolinks.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "6b46543e-8784-4c36-970a-ed779fd6899b", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "body": "[{\"id\":6214208,\"key_prefix\":\"LIST-\",\"url_template\":\"https://example.com/list1/\",\"is_alphanumeric\":true},{\"id\":6214209,\"key_prefix\":\"LISTED-\",\"url_template\":\"https://example.com/list2/\",\"is_alphanumeric\":false}]", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:52 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"fe94434b76cb272acea19e422afda92332aae93faf10354bc617a3360716a141\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4975", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "25", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AA38:2616CE:B40A4C:D3439E:674F9CA4" - } - }, - "uuid": "6b46543e-8784-4c36-970a-ed779fd6899b", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-github-api-test-autolinks", - "requiredScenarioState": "scenario-1-repos-Alaurant-github-api-test-autolinks-2", - "newScenarioState": "scenario-1-repos-Alaurant-github-api-test-autolinks-3", - "insertionIndex": 6 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/7-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/7-r_a_g_autolinks.json deleted file mode 100644 index 42ce6b3388..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/7-r_a_g_autolinks.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "id": "e1029d4b-a07c-4f57-a043-97e49164bf5a", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "body": "[{\"id\":6214208,\"key_prefix\":\"LIST-\",\"url_template\":\"https://example.com/list1/\",\"is_alphanumeric\":true},{\"id\":6214209,\"key_prefix\":\"LISTED-\",\"url_template\":\"https://example.com/list2/\",\"is_alphanumeric\":false}]", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:53 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"fe94434b76cb272acea19e422afda92332aae93faf10354bc617a3360716a141\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4974", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "26", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB28:271404:A4AC9F:C177E4:674F9CA4" - } - }, - "uuid": "e1029d4b-a07c-4f57-a043-97e49164bf5a", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-github-api-test-autolinks", - "requiredScenarioState": "scenario-1-repos-Alaurant-github-api-test-autolinks-3", - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/8-r_a_g_autolinks_6214208.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/8-r_a_g_autolinks_6214208.json deleted file mode 100644 index 524bb8a8dc..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/8-r_a_g_autolinks_6214208.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "affffb27-b98a-4457-9ea5-3c7c952d9bfb", - "name": "repos_alaurant_github-api-test_autolinks_6214208", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214208", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:53 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4973", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "27", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "AB2C:32381D:19A924:1E57CD:674F9CA5" - } - }, - "uuid": "affffb27-b98a-4457-9ea5-3c7c952d9bfb", - "persistent": true, - "insertionIndex": 8 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/9-r_a_g_autolinks_6214209.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/9-r_a_g_autolinks_6214209.json deleted file mode 100644 index b5cf4ec9de..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testListAllAutolinks/mappings/9-r_a_g_autolinks_6214209.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "b4141f4b-4ca3-4a1c-b507-08a861c87340", - "name": "repos_alaurant_github-api-test_autolinks_6214209", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214209", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:53 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4972", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "28", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "AB2D:259AD1:AD6833:CCA19E:674F9CA5" - } - }, - "uuid": "b4141f4b-4ca3-4a1c-b507-08a861c87340", - "persistent": true, - "insertionIndex": 9 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/__files/1-user.json deleted file mode 100644 index 0764c5a936..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": null, - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 7, - "public_gists": 0, - "followers": 3, - "following": 8, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-11-27T04:01:41Z", - "private_gists": 0, - "total_private_repos": 3, - "owned_private_repos": 3, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/__files/2-r_a_github-api-test.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/__files/2-r_a_github-api-test.json deleted file mode 100644 index 5e34f49aad..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/__files/2-r_a_github-api-test.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "id": 895799232, - "node_id": "R_kgDONWTPwA", - "name": "github-api-test", - "full_name": "Alaurant/github-api-test", - "private": true, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/github-api-test", - "description": null, - "fork": false, - "url": "https://api.github.com/repos/Alaurant/github-api-test", - "forks_url": "https://api.github.com/repos/Alaurant/github-api-test/forks", - "keys_url": "https://api.github.com/repos/Alaurant/github-api-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/github-api-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/github-api-test/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/github-api-test/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/github-api-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/github-api-test/events", - "assignees_url": "https://api.github.com/repos/Alaurant/github-api-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/github-api-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/github-api-test/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/github-api-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/github-api-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/github-api-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/github-api-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/github-api-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/github-api-test/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/github-api-test/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/github-api-test/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/github-api-test/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/github-api-test/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/github-api-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/github-api-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/github-api-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/github-api-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/github-api-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/github-api-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/github-api-test/merges", - "archive_url": "https://api.github.com/repos/Alaurant/github-api-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/github-api-test/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/github-api-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/github-api-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/github-api-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/github-api-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/github-api-test/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/github-api-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/github-api-test/deployments", - "created_at": "2024-11-28T23:44:54Z", - "updated_at": "2024-11-28T23:44:55Z", - "pushed_at": "2024-11-28T23:44:55Z", - "git_url": "git://github.com/Alaurant/github-api-test.git", - "ssh_url": "git@github.com:Alaurant/github-api-test.git", - "clone_url": "https://github.com/Alaurant/github-api-test.git", - "svn_url": "https://github.com/Alaurant/github-api-test", - "homepage": null, - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "private", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "AJ7BLWH4VOGNQPWHKJHLRCTHJ6O5G", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "network_count": 0, - "subscribers_count": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/1-user.json deleted file mode 100644 index 9d91294677..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "a1c0eb19-f0f1-4359-b22a-832a141db3e7", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:54 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"8bdc3eaf7312491c8eb245323f2eb3004212814ef5f8184104effa4b32f6b27c\"", - "Last-Modified": "Wed, 27 Nov 2024 04:01:41 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4971", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "29", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB35:25CB59:B00D25:CF469E:674F9CA6" - } - }, - "uuid": "a1c0eb19-f0f1-4359-b22a-832a141db3e7", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/2-r_a_github-api-test.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/2-r_a_github-api-test.json deleted file mode 100644 index c1437c1acf..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/2-r_a_github-api-test.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "9c9e2a60-aeb2-4314-8c97-3263084ed857", - "name": "repos_alaurant_github-api-test", - "request": { - "url": "/repos/Alaurant/github-api-test", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_a_github-api-test.json", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:55 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"94ad6f4d71086bda8c2640d1ba979adc705c9465218c4ca1e55dc20011962ee7\"", - "Last-Modified": "Thu, 28 Nov 2024 23:44:55 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4969", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "31", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB39:321638:1E7483:24179C:674F9CA7" - } - }, - "uuid": "9c9e2a60-aeb2-4314-8c97-3263084ed857", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/3-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/3-r_a_g_autolinks.json deleted file mode 100644 index 608e6c0ffd..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/3-r_a_g_autolinks.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "id": "6b66e6e7-8c08-4fd9-b644-90b84f8f5bf8", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"key_prefix\":\"JIRA-\",\"url_template\":\"https://example.com/test/\",\"is_alphanumeric\":false}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 201, - "body": "{\"id\":6214212,\"key_prefix\":\"JIRA-\",\"url_template\":\"https://example.com/test/\",\"is_alphanumeric\":false}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:56 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"dd07a13b3219e53d610f3dc3c3f3261e0f56b5b9e02c03bef2c21659e19c8875\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4968", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "32", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB3D:275BE1:A98B5B:C65DE1:674F9CA7" - } - }, - "uuid": "6b66e6e7-8c08-4fd9-b644-90b84f8f5bf8", - "persistent": true, - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/4-r_a_g_autolinks_6214212.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/4-r_a_g_autolinks_6214212.json deleted file mode 100644 index 20eee37749..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/4-r_a_g_autolinks_6214212.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "3c2a5120-9645-4bbf-9645-ee04be962ae2", - "name": "repos_alaurant_github-api-test_autolinks_6214212", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214212", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "body": "{\"id\":6214212,\"key_prefix\":\"JIRA-\",\"url_template\":\"https://example.com/test/\",\"is_alphanumeric\":false}", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:56 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"dd07a13b3219e53d610f3dc3c3f3261e0f56b5b9e02c03bef2c21659e19c8875\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4967", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "33", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB3E:25E009:B3DC62:D3161D:674F9CA8" - } - }, - "uuid": "3c2a5120-9645-4bbf-9645-ee04be962ae2", - "persistent": true, - "insertionIndex": 4 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/5-r_a_g_autolinks_6214212.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/5-r_a_g_autolinks_6214212.json deleted file mode 100644 index b72ed1961f..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/5-r_a_g_autolinks_6214212.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "3ed2b3a2-3cc1-4382-86a8-251d4791104b", - "name": "repos_alaurant_github-api-test_autolinks_6214212", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks/6214212", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:57 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4966", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "34", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "AB42:25DAE6:BD2DEF:DC679E:674F9CA9" - } - }, - "uuid": "3ed2b3a2-3cc1-4382-86a8-251d4791104b", - "persistent": true, - "insertionIndex": 5 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/6-r_a_g_autolinks.json b/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/6-r_a_g_autolinks.json deleted file mode 100644 index ce3fe6adc9..0000000000 --- a/src/test/resources/org/kohsuke/github/GHAutolinkTest/wiremock/testReadAutolink/mappings/6-r_a_g_autolinks.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "db9e25ad-fa61-44a4-ab74-c430bd85d6bb", - "name": "repos_alaurant_github-api-test_autolinks", - "request": { - "url": "/repos/Alaurant/github-api-test/autolinks", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "body": "[]", - "headers": { - "Date": "Wed, 04 Dec 2024 00:04:57 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "\"5b744729737bd28d14aeb327919c263d8af99640a7701726d7b2320a638b5c76\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4965", - "X-RateLimit-Reset": "1733273750", - "X-RateLimit-Used": "35", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AB43:25A8FF:B7347B:D66E29:674F9CA9" - } - }, - "uuid": "db9e25ad-fa61-44a4-ab74-c430bd85d6bb", - "persistent": true, - "insertionIndex": 6 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/1-user.json deleted file mode 100644 index 76578d3e42..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/1-user.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false, - "name": "KIMSIWOO", - "company": "Inha university", - "blog": "", - "location": null, - "email": "sa20207@naver.com", - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": "sa20207@naver.com", - "public_repos": 34, - "public_gists": 0, - "followers": 2, - "following": 2, - "created_at": "2021-07-02T07:40:16Z", - "updated_at": "2025-03-03T13:26:53Z" -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/2-r_s_for-test.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/2-r_s_for-test.json deleted file mode 100644 index c2de0d78c0..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/2-r_s_for-test.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "id": 933252913, - "node_id": "R_kgDON6BPMQ", - "name": "for-test", - "full_name": "seate/for-test", - "private": false, - "owner": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/seate/for-test", - "description": "깃허브 테스트용 레포", - "fork": false, - "url": "https://api.github.com/repos/seate/for-test", - "forks_url": "https://api.github.com/repos/seate/for-test/forks", - "keys_url": "https://api.github.com/repos/seate/for-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/seate/for-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/seate/for-test/teams", - "hooks_url": "https://api.github.com/repos/seate/for-test/hooks", - "issue_events_url": "https://api.github.com/repos/seate/for-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/seate/for-test/events", - "assignees_url": "https://api.github.com/repos/seate/for-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/seate/for-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/seate/for-test/tags", - "blobs_url": "https://api.github.com/repos/seate/for-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/seate/for-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/seate/for-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/seate/for-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/seate/for-test/languages", - "stargazers_url": "https://api.github.com/repos/seate/for-test/stargazers", - "contributors_url": "https://api.github.com/repos/seate/for-test/contributors", - "subscribers_url": "https://api.github.com/repos/seate/for-test/subscribers", - "subscription_url": "https://api.github.com/repos/seate/for-test/subscription", - "commits_url": "https://api.github.com/repos/seate/for-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/seate/for-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/seate/for-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/seate/for-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/seate/for-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/seate/for-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/seate/for-test/merges", - "archive_url": "https://api.github.com/repos/seate/for-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/seate/for-test/downloads", - "issues_url": "https://api.github.com/repos/seate/for-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/seate/for-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/seate/for-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/seate/for-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/seate/for-test/labels{/name}", - "releases_url": "https://api.github.com/repos/seate/for-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/seate/for-test/deployments", - "created_at": "2025-02-15T14:21:31Z", - "updated_at": "2025-03-15T16:06:51Z", - "pushed_at": "2025-03-15T16:17:01Z", - "git_url": "git://github.com/seate/for-test.git", - "ssh_url": "git@github.com:seate/for-test.git", - "clone_url": "https://github.com/seate/for-test.git", - "svn_url": "https://github.com/seate/for-test", - "homepage": null, - "size": 62, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "develop", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": true, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/3-r_s_f_pulls_9.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/3-r_s_f_pulls_9.json deleted file mode 100644 index 11347dec30..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/3-r_s_f_pulls_9.json +++ /dev/null @@ -1,372 +0,0 @@ -{ - "url": "https://api.github.com/repos/seate/for-test/pulls/9", - "id": 2395455682, - "node_id": "PR_kwDON6BPMc6Ox8DC", - "html_url": "https://github.com/seate/for-test/pull/9", - "diff_url": "https://github.com/seate/for-test/pull/9.diff", - "patch_url": "https://github.com/seate/for-test/pull/9.patch", - "issue_url": "https://api.github.com/repos/seate/for-test/issues/9", - "number": 9, - "state": "open", - "locked": false, - "title": "github-api enable pull request auto merge test", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "body": "github-api enable pull request auto merge test", - "created_at": "2025-03-15T16:07:53Z", - "updated_at": "2025-03-15T16:18:20Z", - "closed_at": null, - "merged_at": null, - "merge_commit_sha": "25a5888073ee3d2a975e012492950dddb8c346dc", - "assignee": null, - "assignees": [], - "requested_reviewers": [], - "requested_teams": [], - "labels": [], - "milestone": null, - "draft": false, - "commits_url": "https://api.github.com/repos/seate/for-test/pulls/9/commits", - "review_comments_url": "https://api.github.com/repos/seate/for-test/pulls/9/comments", - "review_comment_url": "https://api.github.com/repos/seate/for-test/pulls/comments{/number}", - "comments_url": "https://api.github.com/repos/seate/for-test/issues/9/comments", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/4888b44d7204dd05680e90159af839c8b1194b6d", - "head": { - "label": "seate:test1", - "ref": "test1", - "sha": "4888b44d7204dd05680e90159af839c8b1194b6d", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "repo": { - "id": 933252913, - "node_id": "R_kgDON6BPMQ", - "name": "for-test", - "full_name": "seate/for-test", - "private": false, - "owner": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/seate/for-test", - "description": "깃허브 테스트용 레포", - "fork": false, - "url": "https://api.github.com/repos/seate/for-test", - "forks_url": "https://api.github.com/repos/seate/for-test/forks", - "keys_url": "https://api.github.com/repos/seate/for-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/seate/for-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/seate/for-test/teams", - "hooks_url": "https://api.github.com/repos/seate/for-test/hooks", - "issue_events_url": "https://api.github.com/repos/seate/for-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/seate/for-test/events", - "assignees_url": "https://api.github.com/repos/seate/for-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/seate/for-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/seate/for-test/tags", - "blobs_url": "https://api.github.com/repos/seate/for-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/seate/for-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/seate/for-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/seate/for-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/seate/for-test/languages", - "stargazers_url": "https://api.github.com/repos/seate/for-test/stargazers", - "contributors_url": "https://api.github.com/repos/seate/for-test/contributors", - "subscribers_url": "https://api.github.com/repos/seate/for-test/subscribers", - "subscription_url": "https://api.github.com/repos/seate/for-test/subscription", - "commits_url": "https://api.github.com/repos/seate/for-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/seate/for-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/seate/for-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/seate/for-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/seate/for-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/seate/for-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/seate/for-test/merges", - "archive_url": "https://api.github.com/repos/seate/for-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/seate/for-test/downloads", - "issues_url": "https://api.github.com/repos/seate/for-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/seate/for-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/seate/for-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/seate/for-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/seate/for-test/labels{/name}", - "releases_url": "https://api.github.com/repos/seate/for-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/seate/for-test/deployments", - "created_at": "2025-02-15T14:21:31Z", - "updated_at": "2025-03-15T16:06:51Z", - "pushed_at": "2025-03-15T16:17:01Z", - "git_url": "git://github.com/seate/for-test.git", - "ssh_url": "git@github.com:seate/for-test.git", - "clone_url": "https://github.com/seate/for-test.git", - "svn_url": "https://github.com/seate/for-test", - "homepage": null, - "size": 62, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "develop" - } - }, - "base": { - "label": "seate:develop", - "ref": "develop", - "sha": "2bc9cde73b377e4d0ebda0d19f636644808388f5", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "repo": { - "id": 933252913, - "node_id": "R_kgDON6BPMQ", - "name": "for-test", - "full_name": "seate/for-test", - "private": false, - "owner": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/seate/for-test", - "description": "깃허브 테스트용 레포", - "fork": false, - "url": "https://api.github.com/repos/seate/for-test", - "forks_url": "https://api.github.com/repos/seate/for-test/forks", - "keys_url": "https://api.github.com/repos/seate/for-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/seate/for-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/seate/for-test/teams", - "hooks_url": "https://api.github.com/repos/seate/for-test/hooks", - "issue_events_url": "https://api.github.com/repos/seate/for-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/seate/for-test/events", - "assignees_url": "https://api.github.com/repos/seate/for-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/seate/for-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/seate/for-test/tags", - "blobs_url": "https://api.github.com/repos/seate/for-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/seate/for-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/seate/for-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/seate/for-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/seate/for-test/languages", - "stargazers_url": "https://api.github.com/repos/seate/for-test/stargazers", - "contributors_url": "https://api.github.com/repos/seate/for-test/contributors", - "subscribers_url": "https://api.github.com/repos/seate/for-test/subscribers", - "subscription_url": "https://api.github.com/repos/seate/for-test/subscription", - "commits_url": "https://api.github.com/repos/seate/for-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/seate/for-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/seate/for-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/seate/for-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/seate/for-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/seate/for-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/seate/for-test/merges", - "archive_url": "https://api.github.com/repos/seate/for-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/seate/for-test/downloads", - "issues_url": "https://api.github.com/repos/seate/for-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/seate/for-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/seate/for-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/seate/for-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/seate/for-test/labels{/name}", - "releases_url": "https://api.github.com/repos/seate/for-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/seate/for-test/deployments", - "created_at": "2025-02-15T14:21:31Z", - "updated_at": "2025-03-15T16:06:51Z", - "pushed_at": "2025-03-15T16:17:01Z", - "git_url": "git://github.com/seate/for-test.git", - "ssh_url": "git@github.com:seate/for-test.git", - "clone_url": "https://github.com/seate/for-test.git", - "svn_url": "https://github.com/seate/for-test", - "homepage": null, - "size": 62, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "develop" - } - }, - "_links": { - "self": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9" - }, - "html": { - "href": "https://github.com/seate/for-test/pull/9" - }, - "issue": { - "href": "https://api.github.com/repos/seate/for-test/issues/9" - }, - "comments": { - "href": "https://api.github.com/repos/seate/for-test/issues/9/comments" - }, - "review_comments": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9/comments" - }, - "review_comment": { - "href": "https://api.github.com/repos/seate/for-test/pulls/comments{/number}" - }, - "commits": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9/commits" - }, - "statuses": { - "href": "https://api.github.com/repos/seate/for-test/statuses/4888b44d7204dd05680e90159af839c8b1194b6d" - } - }, - "author_association": "OWNER", - "auto_merge": { - "enabled_by": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "merge_method": "merge", - "commit_title": "This is commit title.", - "commit_message": "This is commit body." - }, - "active_lock_reason": null, - "merged": false, - "mergeable": true, - "rebaseable": true, - "mergeable_state": "blocked", - "merged_by": null, - "comments": 1, - "review_comments": 0, - "maintainer_can_modify": false, - "commits": 16, - "additions": 642, - "deletions": 0, - "changed_files": 19 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/6-r_s_f_pulls_9.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/6-r_s_f_pulls_9.json deleted file mode 100644 index 11347dec30..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/6-r_s_f_pulls_9.json +++ /dev/null @@ -1,372 +0,0 @@ -{ - "url": "https://api.github.com/repos/seate/for-test/pulls/9", - "id": 2395455682, - "node_id": "PR_kwDON6BPMc6Ox8DC", - "html_url": "https://github.com/seate/for-test/pull/9", - "diff_url": "https://github.com/seate/for-test/pull/9.diff", - "patch_url": "https://github.com/seate/for-test/pull/9.patch", - "issue_url": "https://api.github.com/repos/seate/for-test/issues/9", - "number": 9, - "state": "open", - "locked": false, - "title": "github-api enable pull request auto merge test", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "body": "github-api enable pull request auto merge test", - "created_at": "2025-03-15T16:07:53Z", - "updated_at": "2025-03-15T16:18:20Z", - "closed_at": null, - "merged_at": null, - "merge_commit_sha": "25a5888073ee3d2a975e012492950dddb8c346dc", - "assignee": null, - "assignees": [], - "requested_reviewers": [], - "requested_teams": [], - "labels": [], - "milestone": null, - "draft": false, - "commits_url": "https://api.github.com/repos/seate/for-test/pulls/9/commits", - "review_comments_url": "https://api.github.com/repos/seate/for-test/pulls/9/comments", - "review_comment_url": "https://api.github.com/repos/seate/for-test/pulls/comments{/number}", - "comments_url": "https://api.github.com/repos/seate/for-test/issues/9/comments", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/4888b44d7204dd05680e90159af839c8b1194b6d", - "head": { - "label": "seate:test1", - "ref": "test1", - "sha": "4888b44d7204dd05680e90159af839c8b1194b6d", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "repo": { - "id": 933252913, - "node_id": "R_kgDON6BPMQ", - "name": "for-test", - "full_name": "seate/for-test", - "private": false, - "owner": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/seate/for-test", - "description": "깃허브 테스트용 레포", - "fork": false, - "url": "https://api.github.com/repos/seate/for-test", - "forks_url": "https://api.github.com/repos/seate/for-test/forks", - "keys_url": "https://api.github.com/repos/seate/for-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/seate/for-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/seate/for-test/teams", - "hooks_url": "https://api.github.com/repos/seate/for-test/hooks", - "issue_events_url": "https://api.github.com/repos/seate/for-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/seate/for-test/events", - "assignees_url": "https://api.github.com/repos/seate/for-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/seate/for-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/seate/for-test/tags", - "blobs_url": "https://api.github.com/repos/seate/for-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/seate/for-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/seate/for-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/seate/for-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/seate/for-test/languages", - "stargazers_url": "https://api.github.com/repos/seate/for-test/stargazers", - "contributors_url": "https://api.github.com/repos/seate/for-test/contributors", - "subscribers_url": "https://api.github.com/repos/seate/for-test/subscribers", - "subscription_url": "https://api.github.com/repos/seate/for-test/subscription", - "commits_url": "https://api.github.com/repos/seate/for-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/seate/for-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/seate/for-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/seate/for-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/seate/for-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/seate/for-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/seate/for-test/merges", - "archive_url": "https://api.github.com/repos/seate/for-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/seate/for-test/downloads", - "issues_url": "https://api.github.com/repos/seate/for-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/seate/for-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/seate/for-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/seate/for-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/seate/for-test/labels{/name}", - "releases_url": "https://api.github.com/repos/seate/for-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/seate/for-test/deployments", - "created_at": "2025-02-15T14:21:31Z", - "updated_at": "2025-03-15T16:06:51Z", - "pushed_at": "2025-03-15T16:17:01Z", - "git_url": "git://github.com/seate/for-test.git", - "ssh_url": "git@github.com:seate/for-test.git", - "clone_url": "https://github.com/seate/for-test.git", - "svn_url": "https://github.com/seate/for-test", - "homepage": null, - "size": 62, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "develop" - } - }, - "base": { - "label": "seate:develop", - "ref": "develop", - "sha": "2bc9cde73b377e4d0ebda0d19f636644808388f5", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "repo": { - "id": 933252913, - "node_id": "R_kgDON6BPMQ", - "name": "for-test", - "full_name": "seate/for-test", - "private": false, - "owner": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/seate/for-test", - "description": "깃허브 테스트용 레포", - "fork": false, - "url": "https://api.github.com/repos/seate/for-test", - "forks_url": "https://api.github.com/repos/seate/for-test/forks", - "keys_url": "https://api.github.com/repos/seate/for-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/seate/for-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/seate/for-test/teams", - "hooks_url": "https://api.github.com/repos/seate/for-test/hooks", - "issue_events_url": "https://api.github.com/repos/seate/for-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/seate/for-test/events", - "assignees_url": "https://api.github.com/repos/seate/for-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/seate/for-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/seate/for-test/tags", - "blobs_url": "https://api.github.com/repos/seate/for-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/seate/for-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/seate/for-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/seate/for-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/seate/for-test/languages", - "stargazers_url": "https://api.github.com/repos/seate/for-test/stargazers", - "contributors_url": "https://api.github.com/repos/seate/for-test/contributors", - "subscribers_url": "https://api.github.com/repos/seate/for-test/subscribers", - "subscription_url": "https://api.github.com/repos/seate/for-test/subscription", - "commits_url": "https://api.github.com/repos/seate/for-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/seate/for-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/seate/for-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/seate/for-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/seate/for-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/seate/for-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/seate/for-test/merges", - "archive_url": "https://api.github.com/repos/seate/for-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/seate/for-test/downloads", - "issues_url": "https://api.github.com/repos/seate/for-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/seate/for-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/seate/for-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/seate/for-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/seate/for-test/labels{/name}", - "releases_url": "https://api.github.com/repos/seate/for-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/seate/for-test/deployments", - "created_at": "2025-02-15T14:21:31Z", - "updated_at": "2025-03-15T16:06:51Z", - "pushed_at": "2025-03-15T16:17:01Z", - "git_url": "git://github.com/seate/for-test.git", - "ssh_url": "git@github.com:seate/for-test.git", - "clone_url": "https://github.com/seate/for-test.git", - "svn_url": "https://github.com/seate/for-test", - "homepage": null, - "size": 62, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "develop" - } - }, - "_links": { - "self": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9" - }, - "html": { - "href": "https://github.com/seate/for-test/pull/9" - }, - "issue": { - "href": "https://api.github.com/repos/seate/for-test/issues/9" - }, - "comments": { - "href": "https://api.github.com/repos/seate/for-test/issues/9/comments" - }, - "review_comments": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9/comments" - }, - "review_comment": { - "href": "https://api.github.com/repos/seate/for-test/pulls/comments{/number}" - }, - "commits": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9/commits" - }, - "statuses": { - "href": "https://api.github.com/repos/seate/for-test/statuses/4888b44d7204dd05680e90159af839c8b1194b6d" - } - }, - "author_association": "OWNER", - "auto_merge": { - "enabled_by": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "merge_method": "merge", - "commit_title": "This is commit title.", - "commit_message": "This is commit body." - }, - "active_lock_reason": null, - "merged": false, - "mergeable": true, - "rebaseable": true, - "mergeable_state": "blocked", - "merged_by": null, - "comments": 1, - "review_comments": 0, - "maintainer_can_modify": false, - "commits": 16, - "additions": 642, - "deletions": 0, - "changed_files": 19 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/7-users_seate.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/7-users_seate.json deleted file mode 100644 index ae11f23591..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/__files/7-users_seate.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false, - "name": "KIMSIWOO", - "company": "Inha university", - "blog": "", - "location": null, - "email": "sa20207@naver.com", - "hireable": null, - "bio": null, - "twitter_username": null, - "public_repos": 34, - "public_gists": 0, - "followers": 2, - "following": 2, - "created_at": "2021-07-02T07:40:16Z", - "updated_at": "2025-03-03T13:26:53Z" -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/1-user.json deleted file mode 100644 index 4b252141e4..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/1-user.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "08dbdf10-b416-4ff3-b2f8-3985f3f99bb9", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Sat, 15 Mar 2025 18:13:24 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"91439c9cd22b1066c90ef899df4f995dcda9ed34b86d5e107b7c311aaaff2136\"", - "Last-Modified": "Mon, 03 Mar 2025 13:26:53 GMT", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4989", - "X-RateLimit-Reset": "1742065904", - "X-RateLimit-Used": "11", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "F688:2B46D8:3A9875:59C85D:67D5C344" - } - }, - "uuid": "08dbdf10-b416-4ff3-b2f8-3985f3f99bb9", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/2-r_s_for-test.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/2-r_s_for-test.json deleted file mode 100644 index 6fcd708edf..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/2-r_s_for-test.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "efe9930f-f284-49cb-ac98-1870d22d0454", - "name": "repos_seate_for-test", - "request": { - "url": "/repos/seate/for-test", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_s_for-test.json", - "headers": { - "Date": "Sat, 15 Mar 2025 18:13:27 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"9181d2d37a58759c6739fb93cdf26cbc7b9cc04f34e87456932f65921cb5473d\"", - "Last-Modified": "Sat, 15 Mar 2025 16:06:51 GMT", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "repo", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4984", - "X-RateLimit-Reset": "1742065904", - "X-RateLimit-Used": "16", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "F68A:165A85:3BCFDE:5B22D9:67D5C347" - } - }, - "uuid": "efe9930f-f284-49cb-ac98-1870d22d0454", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/3-r_s_f_pulls_9.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/3-r_s_f_pulls_9.json deleted file mode 100644 index f3a8eab80c..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/3-r_s_f_pulls_9.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "4b26d080-5f51-45ea-90b9-dfbe0751cdb5", - "name": "repos_seate_for-test_pulls_9", - "request": { - "url": "/repos/seate/for-test/pulls/9", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "3-r_s_f_pulls_9.json", - "headers": { - "Date": "Sat, 15 Mar 2025 18:13:27 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"4cb91abd4bd5effc3228763b88c5abec155f063e483efaa6ba284bb351e27687\"", - "Last-Modified": "Sat, 15 Mar 2025 16:18:20 GMT", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4983", - "X-RateLimit-Reset": "1742065904", - "X-RateLimit-Used": "17", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "F68B:15724C:3AAF79:5A026E:67D5C347" - } - }, - "uuid": "4b26d080-5f51-45ea-90b9-dfbe0751cdb5", - "persistent": true, - "scenarioName": "scenario-1-repos-seate-for-test-pulls-9", - "requiredScenarioState": "Started", - "newScenarioState": "scenario-1-repos-seate-for-test-pulls-9-2", - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/4-graphql.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/4-graphql.json deleted file mode 100644 index 42db1e78ba..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/4-graphql.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "89c6825e-6277-4ad0-a9f0-d0cb70e5a15b", - "name": "graphql", - "request": { - "url": "/graphql", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"query\":\"query GetPullRequestID { repository(name: \\\"for-test\\\", owner: \\\"seate\\\") { pullRequest(number: 9) { id } } }\"}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 200, - "body": "{\"data\":{\"repository\":{\"pullRequest\":{\"id\":\"PR_kwDON6BPMc6Ox8DC\"}}}}", - "headers": { - "Date": "Sat, 15 Mar 2025 18:13:28 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "repo", - "X-GitHub-Media-Type": "github.v4; format=json", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4981", - "X-RateLimit-Reset": "1742063501", - "X-RateLimit-Used": "19", - "X-RateLimit-Resource": "graphql", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "F68C:2403B3:120286:1B2D2F:67D5C348" - } - }, - "uuid": "89c6825e-6277-4ad0-a9f0-d0cb70e5a15b", - "persistent": true, - "insertionIndex": 4 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/5-graphql.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/5-graphql.json deleted file mode 100644 index 7aff47b1cf..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/5-graphql.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "ff9bdb46-fb2a-44c2-a164-9a790e11c26c", - "name": "graphql", - "request": { - "url": "/graphql", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"query\":\"mutation EnableAutoMerge { enablePullRequestAutoMerge(input: { pullRequestId: \\\"PR_kwDON6BPMc6Ox8DC\\\" authorEmail: \\\"sa20207@naver.com\\\" clientMutationId: \\\"github-api\\\" commitBody: \\\"This is commit body.\\\" commitHeadline: \\\"This is commit title.\\\" expectedHeadOid: \\\"4888b44d7204dd05680e90159af839c8b1194b6d\\\" mergeMethod: MERGE}) { pullRequest { id } } }\"}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 200, - "body": "{\"data\":{\"enablePullRequestAutoMerge\":{\"pullRequest\":{\"id\":\"PR_kwDON6BPMc6Ox8DC\"}}}}", - "headers": { - "Date": "Sat, 15 Mar 2025 18:13:28 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "repo", - "X-GitHub-Media-Type": "github.v4; format=json", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4980", - "X-RateLimit-Reset": "1742063501", - "X-RateLimit-Used": "20", - "X-RateLimit-Resource": "graphql", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "F68D:4F3EE:3B15C8:5A6881:67D5C348" - } - }, - "uuid": "ff9bdb46-fb2a-44c2-a164-9a790e11c26c", - "persistent": true, - "insertionIndex": 5 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/6-r_s_f_pulls_9.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/6-r_s_f_pulls_9.json deleted file mode 100644 index f25e8a33f0..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/6-r_s_f_pulls_9.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "id": "0dd48f53-a8fb-4df8-ba9e-946146f68a33", - "name": "repos_seate_for-test_pulls_9", - "request": { - "url": "/repos/seate/for-test/pulls/9", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "6-r_s_f_pulls_9.json", - "headers": { - "Date": "Sat, 15 Mar 2025 18:13:29 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"4cb91abd4bd5effc3228763b88c5abec155f063e483efaa6ba284bb351e27687\"", - "Last-Modified": "Sat, 15 Mar 2025 16:18:20 GMT", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4982", - "X-RateLimit-Reset": "1742065904", - "X-RateLimit-Used": "18", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "F68E:7ED0E:3A2A32:597D10:67D5C348" - } - }, - "uuid": "0dd48f53-a8fb-4df8-ba9e-946146f68a33", - "persistent": true, - "scenarioName": "scenario-1-repos-seate-for-test-pulls-9", - "requiredScenarioState": "scenario-1-repos-seate-for-test-pulls-9-2", - "insertionIndex": 6 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/7-users_seate.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/7-users_seate.json deleted file mode 100644 index 51c6c8da18..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMerge/mappings/7-users_seate.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "90286178-d879-4d06-ac33-48c714b16fc2", - "name": "users_seate", - "request": { - "url": "/users/seate", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "7-users_seate.json", - "headers": { - "Date": "Sat, 15 Mar 2025 18:13:29 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"0e08109bbc9b14a5d7838fffe7e57d5025e9ee8825089eb2c05f3681b890cbf4\"", - "Last-Modified": "Mon, 03 Mar 2025 13:26:53 GMT", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4981", - "X-RateLimit-Reset": "1742065904", - "X-RateLimit-Used": "19", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "F68F:124DB4:3CBA1A:5C0D00:67D5C349" - } - }, - "uuid": "90286178-d879-4d06-ac33-48c714b16fc2", - "persistent": true, - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/1-user.json deleted file mode 100644 index 76578d3e42..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/1-user.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false, - "name": "KIMSIWOO", - "company": "Inha university", - "blog": "", - "location": null, - "email": "sa20207@naver.com", - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": "sa20207@naver.com", - "public_repos": 34, - "public_gists": 0, - "followers": 2, - "following": 2, - "created_at": "2021-07-02T07:40:16Z", - "updated_at": "2025-03-03T13:26:53Z" -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/2-r_s_for-test.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/2-r_s_for-test.json deleted file mode 100644 index c2de0d78c0..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/2-r_s_for-test.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "id": 933252913, - "node_id": "R_kgDON6BPMQ", - "name": "for-test", - "full_name": "seate/for-test", - "private": false, - "owner": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/seate/for-test", - "description": "깃허브 테스트용 레포", - "fork": false, - "url": "https://api.github.com/repos/seate/for-test", - "forks_url": "https://api.github.com/repos/seate/for-test/forks", - "keys_url": "https://api.github.com/repos/seate/for-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/seate/for-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/seate/for-test/teams", - "hooks_url": "https://api.github.com/repos/seate/for-test/hooks", - "issue_events_url": "https://api.github.com/repos/seate/for-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/seate/for-test/events", - "assignees_url": "https://api.github.com/repos/seate/for-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/seate/for-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/seate/for-test/tags", - "blobs_url": "https://api.github.com/repos/seate/for-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/seate/for-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/seate/for-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/seate/for-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/seate/for-test/languages", - "stargazers_url": "https://api.github.com/repos/seate/for-test/stargazers", - "contributors_url": "https://api.github.com/repos/seate/for-test/contributors", - "subscribers_url": "https://api.github.com/repos/seate/for-test/subscribers", - "subscription_url": "https://api.github.com/repos/seate/for-test/subscription", - "commits_url": "https://api.github.com/repos/seate/for-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/seate/for-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/seate/for-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/seate/for-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/seate/for-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/seate/for-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/seate/for-test/merges", - "archive_url": "https://api.github.com/repos/seate/for-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/seate/for-test/downloads", - "issues_url": "https://api.github.com/repos/seate/for-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/seate/for-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/seate/for-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/seate/for-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/seate/for-test/labels{/name}", - "releases_url": "https://api.github.com/repos/seate/for-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/seate/for-test/deployments", - "created_at": "2025-02-15T14:21:31Z", - "updated_at": "2025-03-15T16:06:51Z", - "pushed_at": "2025-03-15T16:17:01Z", - "git_url": "git://github.com/seate/for-test.git", - "ssh_url": "git@github.com:seate/for-test.git", - "clone_url": "https://github.com/seate/for-test.git", - "svn_url": "https://github.com/seate/for-test", - "homepage": null, - "size": 62, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "develop", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": true, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/3-r_s_f_pulls_9.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/3-r_s_f_pulls_9.json deleted file mode 100644 index 11347dec30..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/__files/3-r_s_f_pulls_9.json +++ /dev/null @@ -1,372 +0,0 @@ -{ - "url": "https://api.github.com/repos/seate/for-test/pulls/9", - "id": 2395455682, - "node_id": "PR_kwDON6BPMc6Ox8DC", - "html_url": "https://github.com/seate/for-test/pull/9", - "diff_url": "https://github.com/seate/for-test/pull/9.diff", - "patch_url": "https://github.com/seate/for-test/pull/9.patch", - "issue_url": "https://api.github.com/repos/seate/for-test/issues/9", - "number": 9, - "state": "open", - "locked": false, - "title": "github-api enable pull request auto merge test", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "body": "github-api enable pull request auto merge test", - "created_at": "2025-03-15T16:07:53Z", - "updated_at": "2025-03-15T16:18:20Z", - "closed_at": null, - "merged_at": null, - "merge_commit_sha": "25a5888073ee3d2a975e012492950dddb8c346dc", - "assignee": null, - "assignees": [], - "requested_reviewers": [], - "requested_teams": [], - "labels": [], - "milestone": null, - "draft": false, - "commits_url": "https://api.github.com/repos/seate/for-test/pulls/9/commits", - "review_comments_url": "https://api.github.com/repos/seate/for-test/pulls/9/comments", - "review_comment_url": "https://api.github.com/repos/seate/for-test/pulls/comments{/number}", - "comments_url": "https://api.github.com/repos/seate/for-test/issues/9/comments", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/4888b44d7204dd05680e90159af839c8b1194b6d", - "head": { - "label": "seate:test1", - "ref": "test1", - "sha": "4888b44d7204dd05680e90159af839c8b1194b6d", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "repo": { - "id": 933252913, - "node_id": "R_kgDON6BPMQ", - "name": "for-test", - "full_name": "seate/for-test", - "private": false, - "owner": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/seate/for-test", - "description": "깃허브 테스트용 레포", - "fork": false, - "url": "https://api.github.com/repos/seate/for-test", - "forks_url": "https://api.github.com/repos/seate/for-test/forks", - "keys_url": "https://api.github.com/repos/seate/for-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/seate/for-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/seate/for-test/teams", - "hooks_url": "https://api.github.com/repos/seate/for-test/hooks", - "issue_events_url": "https://api.github.com/repos/seate/for-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/seate/for-test/events", - "assignees_url": "https://api.github.com/repos/seate/for-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/seate/for-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/seate/for-test/tags", - "blobs_url": "https://api.github.com/repos/seate/for-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/seate/for-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/seate/for-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/seate/for-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/seate/for-test/languages", - "stargazers_url": "https://api.github.com/repos/seate/for-test/stargazers", - "contributors_url": "https://api.github.com/repos/seate/for-test/contributors", - "subscribers_url": "https://api.github.com/repos/seate/for-test/subscribers", - "subscription_url": "https://api.github.com/repos/seate/for-test/subscription", - "commits_url": "https://api.github.com/repos/seate/for-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/seate/for-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/seate/for-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/seate/for-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/seate/for-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/seate/for-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/seate/for-test/merges", - "archive_url": "https://api.github.com/repos/seate/for-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/seate/for-test/downloads", - "issues_url": "https://api.github.com/repos/seate/for-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/seate/for-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/seate/for-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/seate/for-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/seate/for-test/labels{/name}", - "releases_url": "https://api.github.com/repos/seate/for-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/seate/for-test/deployments", - "created_at": "2025-02-15T14:21:31Z", - "updated_at": "2025-03-15T16:06:51Z", - "pushed_at": "2025-03-15T16:17:01Z", - "git_url": "git://github.com/seate/for-test.git", - "ssh_url": "git@github.com:seate/for-test.git", - "clone_url": "https://github.com/seate/for-test.git", - "svn_url": "https://github.com/seate/for-test", - "homepage": null, - "size": 62, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "develop" - } - }, - "base": { - "label": "seate:develop", - "ref": "develop", - "sha": "2bc9cde73b377e4d0ebda0d19f636644808388f5", - "user": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "repo": { - "id": 933252913, - "node_id": "R_kgDON6BPMQ", - "name": "for-test", - "full_name": "seate/for-test", - "private": false, - "owner": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/seate/for-test", - "description": "깃허브 테스트용 레포", - "fork": false, - "url": "https://api.github.com/repos/seate/for-test", - "forks_url": "https://api.github.com/repos/seate/for-test/forks", - "keys_url": "https://api.github.com/repos/seate/for-test/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/seate/for-test/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/seate/for-test/teams", - "hooks_url": "https://api.github.com/repos/seate/for-test/hooks", - "issue_events_url": "https://api.github.com/repos/seate/for-test/issues/events{/number}", - "events_url": "https://api.github.com/repos/seate/for-test/events", - "assignees_url": "https://api.github.com/repos/seate/for-test/assignees{/user}", - "branches_url": "https://api.github.com/repos/seate/for-test/branches{/branch}", - "tags_url": "https://api.github.com/repos/seate/for-test/tags", - "blobs_url": "https://api.github.com/repos/seate/for-test/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/seate/for-test/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/seate/for-test/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/seate/for-test/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/seate/for-test/statuses/{sha}", - "languages_url": "https://api.github.com/repos/seate/for-test/languages", - "stargazers_url": "https://api.github.com/repos/seate/for-test/stargazers", - "contributors_url": "https://api.github.com/repos/seate/for-test/contributors", - "subscribers_url": "https://api.github.com/repos/seate/for-test/subscribers", - "subscription_url": "https://api.github.com/repos/seate/for-test/subscription", - "commits_url": "https://api.github.com/repos/seate/for-test/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/seate/for-test/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/seate/for-test/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/seate/for-test/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/seate/for-test/contents/{+path}", - "compare_url": "https://api.github.com/repos/seate/for-test/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/seate/for-test/merges", - "archive_url": "https://api.github.com/repos/seate/for-test/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/seate/for-test/downloads", - "issues_url": "https://api.github.com/repos/seate/for-test/issues{/number}", - "pulls_url": "https://api.github.com/repos/seate/for-test/pulls{/number}", - "milestones_url": "https://api.github.com/repos/seate/for-test/milestones{/number}", - "notifications_url": "https://api.github.com/repos/seate/for-test/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/seate/for-test/labels{/name}", - "releases_url": "https://api.github.com/repos/seate/for-test/releases{/id}", - "deployments_url": "https://api.github.com/repos/seate/for-test/deployments", - "created_at": "2025-02-15T14:21:31Z", - "updated_at": "2025-03-15T16:06:51Z", - "pushed_at": "2025-03-15T16:17:01Z", - "git_url": "git://github.com/seate/for-test.git", - "ssh_url": "git@github.com:seate/for-test.git", - "clone_url": "https://github.com/seate/for-test.git", - "svn_url": "https://github.com/seate/for-test", - "homepage": null, - "size": 62, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 3, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 3, - "watchers": 0, - "default_branch": "develop" - } - }, - "_links": { - "self": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9" - }, - "html": { - "href": "https://github.com/seate/for-test/pull/9" - }, - "issue": { - "href": "https://api.github.com/repos/seate/for-test/issues/9" - }, - "comments": { - "href": "https://api.github.com/repos/seate/for-test/issues/9/comments" - }, - "review_comments": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9/comments" - }, - "review_comment": { - "href": "https://api.github.com/repos/seate/for-test/pulls/comments{/number}" - }, - "commits": { - "href": "https://api.github.com/repos/seate/for-test/pulls/9/commits" - }, - "statuses": { - "href": "https://api.github.com/repos/seate/for-test/statuses/4888b44d7204dd05680e90159af839c8b1194b6d" - } - }, - "author_association": "OWNER", - "auto_merge": { - "enabled_by": { - "login": "seate", - "id": 86824703, - "node_id": "MDQ6VXNlcjg2ODI0NzAz", - "avatar_url": "https://avatars.githubusercontent.com/u/86824703?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/seate", - "html_url": "https://github.com/seate", - "followers_url": "https://api.github.com/users/seate/followers", - "following_url": "https://api.github.com/users/seate/following{/other_user}", - "gists_url": "https://api.github.com/users/seate/gists{/gist_id}", - "starred_url": "https://api.github.com/users/seate/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/seate/subscriptions", - "organizations_url": "https://api.github.com/users/seate/orgs", - "repos_url": "https://api.github.com/users/seate/repos", - "events_url": "https://api.github.com/users/seate/events{/privacy}", - "received_events_url": "https://api.github.com/users/seate/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "merge_method": "merge", - "commit_title": "This is commit title.", - "commit_message": "This is commit body." - }, - "active_lock_reason": null, - "merged": false, - "mergeable": true, - "rebaseable": true, - "mergeable_state": "blocked", - "merged_by": null, - "comments": 1, - "review_comments": 0, - "maintainer_can_modify": false, - "commits": 16, - "additions": 642, - "deletions": 0, - "changed_files": 19 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/1-user.json deleted file mode 100644 index a6b92d442d..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/1-user.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "931de630-5c54-4bb3-877f-16430f46887f", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Mon, 17 Mar 2025 07:04:43 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"91439c9cd22b1066c90ef899df4f995dcda9ed34b86d5e107b7c311aaaff2136\"", - "Last-Modified": "Mon, 03 Mar 2025 13:26:53 GMT", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4990", - "X-RateLimit-Reset": "1742197445", - "X-RateLimit-Used": "10", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "E025:4F3EE:A59617:F8E5A6:67D7C98B" - } - }, - "uuid": "931de630-5c54-4bb3-877f-16430f46887f", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/2-r_s_for-test.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/2-r_s_for-test.json deleted file mode 100644 index 268fdf44ea..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/2-r_s_for-test.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "cea6580e-f17f-43e1-b5c9-e27077b6ff17", - "name": "repos_seate_for-test", - "request": { - "url": "/repos/seate/for-test", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_s_for-test.json", - "headers": { - "Date": "Mon, 17 Mar 2025 07:04:45 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"9181d2d37a58759c6739fb93cdf26cbc7b9cc04f34e87456932f65921cb5473d\"", - "Last-Modified": "Sat, 15 Mar 2025 16:06:51 GMT", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "repo", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4985", - "X-RateLimit-Reset": "1742197445", - "X-RateLimit-Used": "15", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "E027:1EF85A:16C064:1D9E9C:67D7C98D" - } - }, - "uuid": "cea6580e-f17f-43e1-b5c9-e27077b6ff17", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/3-r_s_f_pulls_9.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/3-r_s_f_pulls_9.json deleted file mode 100644 index 06d04c10ad..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/3-r_s_f_pulls_9.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "88725e34-4c36-4681-bc6a-f82ff05b80ef", - "name": "repos_seate_for-test_pulls_9", - "request": { - "url": "/repos/seate/for-test/pulls/9", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "3-r_s_f_pulls_9.json", - "headers": { - "Date": "Mon, 17 Mar 2025 07:04:46 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"4cb91abd4bd5effc3228763b88c5abec155f063e483efaa6ba284bb351e27687\"", - "Last-Modified": "Sat, 15 Mar 2025 16:18:20 GMT", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4984", - "X-RateLimit-Reset": "1742197445", - "X-RateLimit-Used": "16", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "E028:1F17C6:160FCD:1CEEA4:67D7C98D" - } - }, - "uuid": "88725e34-4c36-4681-bc6a-f82ff05b80ef", - "persistent": true, - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/4-graphql.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/4-graphql.json deleted file mode 100644 index f1e592ffb3..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/4-graphql.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "ab9b1fcc-2e83-46f8-82a7-a5a6b19b9958", - "name": "graphql", - "request": { - "url": "/graphql", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"query\":\"query GetPullRequestID { repository(name: \\\"for-test\\\", owner: \\\"seate\\\") { pullRequest(number: 9) { id } } }\"}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 200, - "body": "{\"data\":{\"repository\":{\"pullRequest\":{\"id\":\"PR_kwDON6BPMc6Ox8DC\"}}}}", - "headers": { - "Date": "Mon, 17 Mar 2025 07:04:46 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "repo", - "X-GitHub-Media-Type": "github.v4; format=json", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4923", - "X-RateLimit-Reset": "1742196376", - "X-RateLimit-Used": "77", - "X-RateLimit-Resource": "graphql", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "E029:3882B9:169857:1D842A:67D7C98E" - } - }, - "uuid": "ab9b1fcc-2e83-46f8-82a7-a5a6b19b9958", - "persistent": true, - "insertionIndex": 4 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/5-graphql.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/5-graphql.json deleted file mode 100644 index 1f2dc6f418..0000000000 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/enablePullRequestAutoMergeFailure/mappings/5-graphql.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "d219868c-dc53-4642-863d-64a268d3c115", - "name": "graphql", - "request": { - "url": "/graphql", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"query\":\"mutation EnableAutoMerge { enablePullRequestAutoMerge(input: { pullRequestId: \\\"PR_kwDON6BPMc6Ox8DC\\\" authorEmail: \\\"failureEmail@gmail.com\\\" clientMutationId: \\\"github-api\\\" commitBody: \\\"This is commit body.\\\" commitHeadline: \\\"This is commit title.\\\" expectedHeadOid: \\\"4888b44d7204dd05680e90159af839c8b1194b6d\\\"}) { pullRequest { id } } }\"}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 200, - "body": "{\"data\":{\"enablePullRequestAutoMerge\":null},\"errors\":[{\"type\":\"UNPROCESSABLE\",\"path\":[\"enablePullRequestAutoMerge\"],\"locations\":[{\"line\":1,\"column\":28}],\"message\":\"seate does not have a verified email, which is required to enable auto-merging.\"}]}", - "headers": { - "Date": "Mon, 17 Mar 2025 07:04:47 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:repo_hook, gist, notifications, read:discussion, read:org, read:project, repo, user:email", - "X-Accepted-OAuth-Scopes": "repo", - "X-GitHub-Media-Type": "github.v4; format=json", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4922", - "X-RateLimit-Reset": "1742196376", - "X-RateLimit-Used": "78", - "X-RateLimit-Resource": "graphql", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "E02A:FA314:AB056F:FE5536:67D7C98E" - } - }, - "uuid": "d219868c-dc53-4642-863d-64a268d3c115", - "persistent": true, - "insertionIndex": 5 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/pullRequestReviewComments/mappings/7-r_h_g_pulls_484_comments.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/pullRequestReviewComments/mappings/7-r_h_g_pulls_484_comments.json index 94ea535e21..c62816d287 100644 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/pullRequestReviewComments/mappings/7-r_h_g_pulls_484_comments.json +++ b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/pullRequestReviewComments/mappings/7-r_h_g_pulls_484_comments.json @@ -11,7 +11,7 @@ }, "bodyPatterns": [ { - "equalToJson": "{\"path\":\"README.md\",\"side\":\"right\",\"line\":2,\"body\":\"A single line review comment\",\"commit_id\":\"07374fe73aff1c2024a8d4114b32406c7a8e89b7\"}", + "equalToJson": "{\"path\":\"README.md\",\"line\":2,\"body\":\"A single line review comment\",\"commit_id\":\"07374fe73aff1c2024a8d4114b32406c7a8e89b7\"}", "ignoreArrayOrder": true, "ignoreExtraElements": false } @@ -55,4 +55,4 @@ "uuid": "43f15589-cf59-4ed5-a2b8-8f6b7ebae791", "persistent": true, "insertionIndex": 7 -} +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/pullRequestReviewComments/mappings/8-r_h_g_pulls_484_comments.json b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/pullRequestReviewComments/mappings/8-r_h_g_pulls_484_comments.json index f335232943..2b80fe4f36 100644 --- a/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/pullRequestReviewComments/mappings/8-r_h_g_pulls_484_comments.json +++ b/src/test/resources/org/kohsuke/github/GHPullRequestTest/wiremock/pullRequestReviewComments/mappings/8-r_h_g_pulls_484_comments.json @@ -11,7 +11,7 @@ }, "bodyPatterns": [ { - "equalToJson": "{\"path\":\"README.md\",\"side\":\"right\",\"start_side\":\"right\",\"line\":3,\"start_line\":2,\"body\":\"A multiline review comment\",\"commit_id\":\"07374fe73aff1c2024a8d4114b32406c7a8e89b7\"}", + "equalToJson": "{\"path\":\"README.md\",\"line\":3,\"start_line\":2,\"body\":\"A multiline review comment\",\"commit_id\":\"07374fe73aff1c2024a8d4114b32406c7a8e89b7\"}", "ignoreArrayOrder": true, "ignoreExtraElements": false } @@ -55,4 +55,4 @@ "uuid": "efe94b1b-7f9c-4bba-9af2-0a7a59a498ab", "persistent": true, "insertionIndex": 8 -} +} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/1-user.json deleted file mode 100644 index a385d2bfd8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": "Brisbane, AUS", - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 14, - "public_gists": 0, - "followers": 4, - "following": 11, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-12-15T04:04:44Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/10-r_a_t_branches.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/10-r_a_t_branches.json deleted file mode 100644 index e9d401004d..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/10-r_a_t_branches.json +++ /dev/null @@ -1,70 +0,0 @@ -[ - { - "name": "main", - "commit": { - "sha": "cc56732e2af71c7c250e5e0e61ac977b52aecd1c", - "url": "https://api.github.com/repos/Alaurant/temp-testFork/commits/cc56732e2af71c7c250e5e0e61ac977b52aecd1c" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/temp-testFork/branches/main/protection" - }, - { - "name": "test-branch1", - "commit": { - "sha": "cc56732e2af71c7c250e5e0e61ac977b52aecd1c", - "url": "https://api.github.com/repos/Alaurant/temp-testFork/commits/cc56732e2af71c7c250e5e0e61ac977b52aecd1c" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/temp-testFork/branches/test-branch1/protection" - }, - { - "name": "test-branch2", - "commit": { - "sha": "cc56732e2af71c7c250e5e0e61ac977b52aecd1c", - "url": "https://api.github.com/repos/Alaurant/temp-testFork/commits/cc56732e2af71c7c250e5e0e61ac977b52aecd1c" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/temp-testFork/branches/test-branch2/protection" - }, - { - "name": "test-branch3", - "commit": { - "sha": "cc56732e2af71c7c250e5e0e61ac977b52aecd1c", - "url": "https://api.github.com/repos/Alaurant/temp-testFork/commits/cc56732e2af71c7c250e5e0e61ac977b52aecd1c" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/temp-testFork/branches/test-branch3/protection" - } -] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/2-r_h_temp-testfork.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/2-r_h_temp-testfork.json deleted file mode 100644 index 87ad2a99ff..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/2-r_h_temp-testfork.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "id": 906237768, - "node_id": "R_kgDONgQXSA", - "name": "temp-testFork", - "full_name": "hub4j-test-org/temp-testFork", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testFork", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:02Z", - "updated_at": "2024-12-20T13:03:03Z", - "pushed_at": "2024-12-20T13:03:03Z", - "git_url": "git://github.com/hub4j-test-org/temp-testFork.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testFork.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testFork.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 18 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/7-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/7-r_h_t_forks.json deleted file mode 100644 index 71155731bc..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/7-r_h_t_forks.json +++ /dev/null @@ -1,312 +0,0 @@ -{ - "id": 906237805, - "node_id": "R_kgDONgQXbQ", - "name": "temp-testFork", - "full_name": "Alaurant/temp-testFork", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/temp-testFork", - "forks_url": "https://api.github.com/repos/Alaurant/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/Alaurant/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/Alaurant/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/Alaurant/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:09Z", - "updated_at": "2024-12-20T13:03:09Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/Alaurant/temp-testFork.git", - "ssh_url": "git@github.com:Alaurant/temp-testFork.git", - "clone_url": "https://github.com/Alaurant/temp-testFork.git", - "svn_url": "https://github.com/Alaurant/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "parent": { - "id": 906237768, - "node_id": "R_kgDONgQXSA", - "name": "temp-testFork", - "full_name": "hub4j-test-org/temp-testFork", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testFork", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:02Z", - "updated_at": "2024-12-20T13:03:06Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/hub4j-test-org/temp-testFork.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testFork.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testFork.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237768, - "node_id": "R_kgDONgQXSA", - "name": "temp-testFork", - "full_name": "hub4j-test-org/temp-testFork", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testFork", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:02Z", - "updated_at": "2024-12-20T13:03:06Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/hub4j-test-org/temp-testFork.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testFork.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testFork.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "network_count": 0, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/8-r_a_temp-testfork.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/8-r_a_temp-testfork.json deleted file mode 100644 index 70be788276..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/8-r_a_temp-testfork.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "id": 906237805, - "node_id": "R_kgDONgQXbQ", - "name": "temp-testFork", - "full_name": "Alaurant/temp-testFork", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/temp-testFork", - "forks_url": "https://api.github.com/repos/Alaurant/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/Alaurant/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/Alaurant/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/Alaurant/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:09Z", - "updated_at": "2024-12-20T13:03:09Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/Alaurant/temp-testFork.git", - "ssh_url": "git@github.com:Alaurant/temp-testFork.git", - "clone_url": "https://github.com/Alaurant/temp-testFork.git", - "svn_url": "https://github.com/Alaurant/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "parent": { - "id": 906237768, - "node_id": "R_kgDONgQXSA", - "name": "temp-testFork", - "full_name": "hub4j-test-org/temp-testFork", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testFork", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:02Z", - "updated_at": "2024-12-20T13:03:06Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/hub4j-test-org/temp-testFork.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testFork.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testFork.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237768, - "node_id": "R_kgDONgQXSA", - "name": "temp-testFork", - "full_name": "hub4j-test-org/temp-testFork", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testFork", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:02Z", - "updated_at": "2024-12-20T13:03:06Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/hub4j-test-org/temp-testFork.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testFork.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testFork.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "enabled" - }, - "secret_scanning_push_protection": { - "status": "enabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/9-r_a_temp-testfork.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/9-r_a_temp-testfork.json deleted file mode 100644 index 70be788276..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/__files/9-r_a_temp-testfork.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "id": 906237805, - "node_id": "R_kgDONgQXbQ", - "name": "temp-testFork", - "full_name": "Alaurant/temp-testFork", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/temp-testFork", - "forks_url": "https://api.github.com/repos/Alaurant/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/Alaurant/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/Alaurant/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/Alaurant/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:09Z", - "updated_at": "2024-12-20T13:03:09Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/Alaurant/temp-testFork.git", - "ssh_url": "git@github.com:Alaurant/temp-testFork.git", - "clone_url": "https://github.com/Alaurant/temp-testFork.git", - "svn_url": "https://github.com/Alaurant/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "parent": { - "id": 906237768, - "node_id": "R_kgDONgQXSA", - "name": "temp-testFork", - "full_name": "hub4j-test-org/temp-testFork", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testFork", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:02Z", - "updated_at": "2024-12-20T13:03:06Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/hub4j-test-org/temp-testFork.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testFork.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testFork.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237768, - "node_id": "R_kgDONgQXSA", - "name": "temp-testFork", - "full_name": "hub4j-test-org/temp-testFork", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testFork", - "description": "A test repository for testing the github-api project: temp-testFork", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testFork", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testFork/deployments", - "created_at": "2024-12-20T13:03:02Z", - "updated_at": "2024-12-20T13:03:06Z", - "pushed_at": "2024-12-20T13:03:08Z", - "git_url": "git://github.com/hub4j-test-org/temp-testFork.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testFork.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testFork.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testFork", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "enabled" - }, - "secret_scanning_push_protection": { - "status": "enabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/1-user.json deleted file mode 100644 index 8d6aa05cdb..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "08691616-b577-4249-a7dc-429bc18c4244", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:01 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"385e08560117e426bff1cdeb255753d2813a21fd716dab4fb6fbce27aa60b10f\"", - "Last-Modified": "Sun, 15 Dec 2024 04:04:44 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4536", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "464", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "19C6:3BD1EB:26FDEE:2E9A5B:67656B05" - } - }, - "uuid": "08691616-b577-4249-a7dc-429bc18c4244", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/10-r_a_t_branches.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/10-r_a_t_branches.json deleted file mode 100644 index a2ea670a82..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/10-r_a_t_branches.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "52fe6c07-92fb-4636-a85d-158938859417", - "name": "repos_alaurant_temp-testfork_branches", - "request": { - "url": "/repos/Alaurant/temp-testFork/branches", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "10-r_a_t_branches.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:14 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"e501e486d5a993dc60ead8b25ae136c13033c082948a20bee0edf5025df6d6cc\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4523", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "477", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "19EE:2E6E0F:D8922:10993F:67656B12" - } - }, - "uuid": "52fe6c07-92fb-4636-a85d-158938859417", - "persistent": true, - "insertionIndex": 10 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/11-r_a_temp-testfork.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/11-r_a_temp-testfork.json deleted file mode 100644 index 1b344a4842..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/11-r_a_temp-testfork.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "1cf8dedd-b4a6-4c34-abef-808e897c3f11", - "name": "repos_alaurant_temp-testfork", - "request": { - "url": "/repos/Alaurant/temp-testFork", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:15 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "delete_repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4522", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "478", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "19F2:24DD67:1750C65:1B2EA4F:67656B12" - } - }, - "uuid": "1cf8dedd-b4a6-4c34-abef-808e897c3f11", - "persistent": true, - "insertionIndex": 11 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/2-r_h_temp-testfork.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/2-r_h_temp-testfork.json deleted file mode 100644 index 800ab3c90f..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/2-r_h_temp-testfork.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "28287013-05d0-471d-aa1b-b8d3668f576c", - "name": "repos_hub4j-test-org_temp-testfork", - "request": { - "url": "/repos/hub4j-test-org/temp-testFork", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_h_temp-testfork.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:06 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"db4699475f6ac92cf3719728738d0ca7464520c78c7becccec7defe1a1342237\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:03 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4531", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "469", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "19D3:2CFAFD:E77BCB:1119D2C:67656B0A" - } - }, - "uuid": "28287013-05d0-471d-aa1b-b8d3668f576c", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/7-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/7-r_h_t_forks.json deleted file mode 100644 index 3dfc496b7c..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/7-r_h_t_forks.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "id": "4ef54cbd-66f3-4aa4-baf6-f02e941385a5", - "name": "repos_hub4j-test-org_temp-testfork_forks", - "request": { - "url": "/repos/hub4j-test-org/temp-testFork/forks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 202, - "bodyFileName": "7-r_h_t_forks.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:09 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4526", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "474", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "19DE:139242:13ED5F9:1760883:67656B0D" - } - }, - "uuid": "4ef54cbd-66f3-4aa4-baf6-f02e941385a5", - "persistent": true, - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/8-r_a_temp-testfork.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/8-r_a_temp-testfork.json deleted file mode 100644 index 9c4c1a8af0..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/8-r_a_temp-testfork.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "id": "c515d8f7-ff23-4299-a35d-eb2608a1e3d7", - "name": "repos_alaurant_temp-testfork", - "request": { - "url": "/repos/Alaurant/temp-testFork", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "8-r_a_temp-testfork.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:10 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"27da55e60c1909f17d020562b8fb04dfc4c058f58a317cbed8c1dc7446c98f13\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:09 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4525", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "475", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "19E3:24DD67:1750AFC:1B2E8AB:67656B0E" - } - }, - "uuid": "c515d8f7-ff23-4299-a35d-eb2608a1e3d7", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-temp-testFork", - "requiredScenarioState": "Started", - "newScenarioState": "scenario-1-repos-Alaurant-temp-testFork-2", - "insertionIndex": 8 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/9-r_a_temp-testfork.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/9-r_a_temp-testfork.json deleted file mode 100644 index b71e47daac..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testFork/mappings/9-r_a_temp-testfork.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "1b689152-841c-4f2c-8998-97ad5b977bb8", - "name": "repos_alaurant_temp-testfork", - "request": { - "url": "/repos/Alaurant/temp-testFork", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "9-r_a_temp-testfork.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:14 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"27da55e60c1909f17d020562b8fb04dfc4c058f58a317cbed8c1dc7446c98f13\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:09 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4524", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "476", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "19ED:139242:13ED7CA:1760A8D:67656B11" - } - }, - "uuid": "1b689152-841c-4f2c-8998-97ad5b977bb8", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-temp-testFork", - "requiredScenarioState": "scenario-1-repos-Alaurant-temp-testFork-2", - "insertionIndex": 9 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/1-user.json deleted file mode 100644 index a385d2bfd8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": "Brisbane, AUS", - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 14, - "public_gists": 0, - "followers": 4, - "following": 11, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-12-15T04:04:44Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/10-r_a_t_branches.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/10-r_a_t_branches.json deleted file mode 100644 index cf9be01c88..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/10-r_a_t_branches.json +++ /dev/null @@ -1,70 +0,0 @@ -[ - { - "name": "main", - "commit": { - "sha": "0bd7d09dfde84e453a2c1d0cdb62adfd7b1adfd6", - "url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/commits/0bd7d09dfde84e453a2c1d0cdb62adfd7b1adfd6" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/branches/main/protection" - }, - { - "name": "test-branch1", - "commit": { - "sha": "0bd7d09dfde84e453a2c1d0cdb62adfd7b1adfd6", - "url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/commits/0bd7d09dfde84e453a2c1d0cdb62adfd7b1adfd6" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/branches/test-branch1/protection" - }, - { - "name": "test-branch2", - "commit": { - "sha": "0bd7d09dfde84e453a2c1d0cdb62adfd7b1adfd6", - "url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/commits/0bd7d09dfde84e453a2c1d0cdb62adfd7b1adfd6" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/branches/test-branch2/protection" - }, - { - "name": "test-branch3", - "commit": { - "sha": "0bd7d09dfde84e453a2c1d0cdb62adfd7b1adfd6", - "url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/commits/0bd7d09dfde84e453a2c1d0cdb62adfd7b1adfd6" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/branches/test-branch3/protection" - } -] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/2-r_h_temp-testforkchangedname.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/2-r_h_temp-testforkchangedname.json deleted file mode 100644 index 4999eb525f..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/2-r_h_temp-testforkchangedname.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "id": 906237934, - "node_id": "R_kgDONgQX7g", - "name": "temp-testForkChangedName", - "full_name": "hub4j-test-org/temp-testForkChangedName", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/deployments", - "created_at": "2024-12-20T13:03:29Z", - "updated_at": "2024-12-20T13:03:33Z", - "pushed_at": "2024-12-20T13:03:30Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkChangedName.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkChangedName.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkChangedName.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 18 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/7-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/7-r_h_t_forks.json deleted file mode 100644 index 108ffed5c1..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/7-r_h_t_forks.json +++ /dev/null @@ -1,312 +0,0 @@ -{ - "id": 906237963, - "node_id": "R_kgDONgQYCw", - "name": "test-fork-with-new-name", - "full_name": "Alaurant/test-fork-with-new-name", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/test-fork-with-new-name", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name", - "forks_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/forks", - "keys_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/events", - "assignees_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/merges", - "archive_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/deployments", - "created_at": "2024-12-20T13:03:36Z", - "updated_at": "2024-12-20T13:03:36Z", - "pushed_at": "2024-12-20T13:03:35Z", - "git_url": "git://github.com/Alaurant/test-fork-with-new-name.git", - "ssh_url": "git@github.com:Alaurant/test-fork-with-new-name.git", - "clone_url": "https://github.com/Alaurant/test-fork-with-new-name.git", - "svn_url": "https://github.com/Alaurant/test-fork-with-new-name", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "parent": { - "id": 906237934, - "node_id": "R_kgDONgQX7g", - "name": "temp-testForkChangedName", - "full_name": "hub4j-test-org/temp-testForkChangedName", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/deployments", - "created_at": "2024-12-20T13:03:29Z", - "updated_at": "2024-12-20T13:03:33Z", - "pushed_at": "2024-12-20T13:03:35Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkChangedName.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkChangedName.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkChangedName.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237934, - "node_id": "R_kgDONgQX7g", - "name": "temp-testForkChangedName", - "full_name": "hub4j-test-org/temp-testForkChangedName", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/deployments", - "created_at": "2024-12-20T13:03:29Z", - "updated_at": "2024-12-20T13:03:33Z", - "pushed_at": "2024-12-20T13:03:35Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkChangedName.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkChangedName.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkChangedName.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "network_count": 0, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/8-r_a_test-fork-with-new-name.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/8-r_a_test-fork-with-new-name.json deleted file mode 100644 index dba3b76a3a..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/8-r_a_test-fork-with-new-name.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "id": 906237963, - "node_id": "R_kgDONgQYCw", - "name": "test-fork-with-new-name", - "full_name": "Alaurant/test-fork-with-new-name", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/test-fork-with-new-name", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name", - "forks_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/forks", - "keys_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/events", - "assignees_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/merges", - "archive_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/deployments", - "created_at": "2024-12-20T13:03:36Z", - "updated_at": "2024-12-20T13:03:36Z", - "pushed_at": "2024-12-20T13:03:35Z", - "git_url": "git://github.com/Alaurant/test-fork-with-new-name.git", - "ssh_url": "git@github.com:Alaurant/test-fork-with-new-name.git", - "clone_url": "https://github.com/Alaurant/test-fork-with-new-name.git", - "svn_url": "https://github.com/Alaurant/test-fork-with-new-name", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "parent": { - "id": 906237934, - "node_id": "R_kgDONgQX7g", - "name": "temp-testForkChangedName", - "full_name": "hub4j-test-org/temp-testForkChangedName", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/deployments", - "created_at": "2024-12-20T13:03:29Z", - "updated_at": "2024-12-20T13:03:33Z", - "pushed_at": "2024-12-20T13:03:36Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkChangedName.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkChangedName.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkChangedName.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237934, - "node_id": "R_kgDONgQX7g", - "name": "temp-testForkChangedName", - "full_name": "hub4j-test-org/temp-testForkChangedName", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/deployments", - "created_at": "2024-12-20T13:03:29Z", - "updated_at": "2024-12-20T13:03:33Z", - "pushed_at": "2024-12-20T13:03:36Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkChangedName.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkChangedName.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkChangedName.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "enabled" - }, - "secret_scanning_push_protection": { - "status": "enabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/9-r_a_test-fork-with-new-name.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/9-r_a_test-fork-with-new-name.json deleted file mode 100644 index dba3b76a3a..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/__files/9-r_a_test-fork-with-new-name.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "id": 906237963, - "node_id": "R_kgDONgQYCw", - "name": "test-fork-with-new-name", - "full_name": "Alaurant/test-fork-with-new-name", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/test-fork-with-new-name", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name", - "forks_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/forks", - "keys_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/events", - "assignees_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/merges", - "archive_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/test-fork-with-new-name/deployments", - "created_at": "2024-12-20T13:03:36Z", - "updated_at": "2024-12-20T13:03:36Z", - "pushed_at": "2024-12-20T13:03:35Z", - "git_url": "git://github.com/Alaurant/test-fork-with-new-name.git", - "ssh_url": "git@github.com:Alaurant/test-fork-with-new-name.git", - "clone_url": "https://github.com/Alaurant/test-fork-with-new-name.git", - "svn_url": "https://github.com/Alaurant/test-fork-with-new-name", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "parent": { - "id": 906237934, - "node_id": "R_kgDONgQX7g", - "name": "temp-testForkChangedName", - "full_name": "hub4j-test-org/temp-testForkChangedName", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/deployments", - "created_at": "2024-12-20T13:03:29Z", - "updated_at": "2024-12-20T13:03:33Z", - "pushed_at": "2024-12-20T13:03:36Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkChangedName.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkChangedName.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkChangedName.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237934, - "node_id": "R_kgDONgQX7g", - "name": "temp-testForkChangedName", - "full_name": "hub4j-test-org/temp-testForkChangedName", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "description": "A test repository for testing the github-api project: temp-testForkChangedName", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkChangedName/deployments", - "created_at": "2024-12-20T13:03:29Z", - "updated_at": "2024-12-20T13:03:33Z", - "pushed_at": "2024-12-20T13:03:36Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkChangedName.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkChangedName.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkChangedName.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkChangedName", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "enabled" - }, - "secret_scanning_push_protection": { - "status": "enabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/1-user.json deleted file mode 100644 index 7b21147a22..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "296851aa-438a-4995-a736-4fe790939978", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:27 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"385e08560117e426bff1cdeb255753d2813a21fd716dab4fb6fbce27aa60b10f\"", - "Last-Modified": "Sun, 15 Dec 2024 04:04:44 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4504", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "496", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1828:139242:13EDC55:1760FEE:67656B1F" - } - }, - "uuid": "296851aa-438a-4995-a736-4fe790939978", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/10-r_a_t_branches.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/10-r_a_t_branches.json deleted file mode 100644 index 76cb0cd00e..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/10-r_a_t_branches.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "ebfac3e9-0535-464d-bf28-88193b68a22f", - "name": "repos_alaurant_test-fork-with-new-name_branches", - "request": { - "url": "/repos/Alaurant/test-fork-with-new-name/branches", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "10-r_a_t_branches.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:41 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"c631fa0760eae27f877eaff9f736d0989178a369351ce7f37fec945ff2c6a285\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4491", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "509", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1852:32E7C9:14E687F:187C166:67656B2D" - } - }, - "uuid": "ebfac3e9-0535-464d-bf28-88193b68a22f", - "persistent": true, - "insertionIndex": 10 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/11-r_a_test-fork-with-new-name.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/11-r_a_test-fork-with-new-name.json deleted file mode 100644 index 7e0bc2a0d8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/11-r_a_test-fork-with-new-name.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "dcdfdace-40b8-4b5e-9687-4b1ae2da61cb", - "name": "repos_alaurant_test-fork-with-new-name", - "request": { - "url": "/repos/Alaurant/test-fork-with-new-name", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:42 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "delete_repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4490", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "510", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "1853:273586:157205C:18F4950:67656B2D" - } - }, - "uuid": "dcdfdace-40b8-4b5e-9687-4b1ae2da61cb", - "persistent": true, - "insertionIndex": 11 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/2-r_h_temp-testforkchangedname.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/2-r_h_temp-testforkchangedname.json deleted file mode 100644 index eda249760a..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/2-r_h_temp-testforkchangedname.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "11509f39-9edb-47dc-a69f-816cfd79fa16", - "name": "repos_hub4j-test-org_temp-testforkchangedname", - "request": { - "url": "/repos/hub4j-test-org/temp-testForkChangedName", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_h_temp-testforkchangedname.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:34 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"99764250f45d4b61c1d15ffad41b53a6e5ef296b162f522210b67cd0214b43c5\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:33 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4499", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "501", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1838:2E6E0F:D8ED8:10A013:67656B25" - } - }, - "uuid": "11509f39-9edb-47dc-a69f-816cfd79fa16", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/7-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/7-r_h_t_forks.json deleted file mode 100644 index 9decf4de30..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/7-r_h_t_forks.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "id": "fdf79883-6cca-4684-8679-38e6a2190127", - "name": "repos_hub4j-test-org_temp-testforkchangedname_forks", - "request": { - "url": "/repos/hub4j-test-org/temp-testForkChangedName/forks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"name\":\"test-fork-with-new-name\"}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 202, - "bodyFileName": "7-r_h_t_forks.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:37 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4494", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "506", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "1843:32E7C9:14E66EE:187BF77:67656B28" - } - }, - "uuid": "fdf79883-6cca-4684-8679-38e6a2190127", - "persistent": true, - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/8-r_a_test-fork-with-new-name.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/8-r_a_test-fork-with-new-name.json deleted file mode 100644 index e3b78e8a79..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/8-r_a_test-fork-with-new-name.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "id": "ffa0ad50-719c-4519-89bf-23bb84b88fa7", - "name": "repos_alaurant_test-fork-with-new-name", - "request": { - "url": "/repos/Alaurant/test-fork-with-new-name", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "8-r_a_test-fork-with-new-name.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:37 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"8abd35382f1e6544398de57cfb7e8fd04978f2c3ec7cdd360b7c8737aa845bd1\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:36 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4493", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "507", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1847:2E6E0F:D8FAA:10A117:67656B29" - } - }, - "uuid": "ffa0ad50-719c-4519-89bf-23bb84b88fa7", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-test-fork-with-new-name", - "requiredScenarioState": "Started", - "newScenarioState": "scenario-1-repos-Alaurant-test-fork-with-new-name-2", - "insertionIndex": 8 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/9-r_a_test-fork-with-new-name.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/9-r_a_test-fork-with-new-name.json deleted file mode 100644 index 1fa85fc0dc..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkChangedName/mappings/9-r_a_test-fork-with-new-name.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "9282fcd8-08cc-4a3a-93d2-42ba0938abe7", - "name": "repos_alaurant_test-fork-with-new-name", - "request": { - "url": "/repos/Alaurant/test-fork-with-new-name", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "9-r_a_test-fork-with-new-name.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:41 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"8abd35382f1e6544398de57cfb7e8fd04978f2c3ec7cdd360b7c8737aa845bd1\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:36 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4492", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "508", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1851:1E9DA:1632513:1A10497:67656B2C" - } - }, - "uuid": "9282fcd8-08cc-4a3a-93d2-42ba0938abe7", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-test-fork-with-new-name", - "requiredScenarioState": "scenario-1-repos-Alaurant-test-fork-with-new-name-2", - "insertionIndex": 9 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/1-user.json deleted file mode 100644 index a385d2bfd8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": "Brisbane, AUS", - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 14, - "public_gists": 0, - "followers": 4, - "following": 11, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-12-15T04:04:44Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/10-r_a_t_branches.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/10-r_a_t_branches.json deleted file mode 100644 index 3465145fea..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/10-r_a_t_branches.json +++ /dev/null @@ -1,19 +0,0 @@ -[ - { - "name": "main", - "commit": { - "sha": "b565d5b9adbaf54f1b35d879f0d98c135ad3d7d8", - "url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/commits/b565d5b9adbaf54f1b35d879f0d98c135ad3d7d8" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/branches/main/protection" - } -] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/2-r_h_temp-testforkdefaultbranchonly.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/2-r_h_temp-testforkdefaultbranchonly.json deleted file mode 100644 index 204cdaf251..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/2-r_h_temp-testforkdefaultbranchonly.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "id": 906237492, - "node_id": "R_kgDONgQWNA", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "hub4j-test-org/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:20Z", - "updated_at": "2024-12-20T13:02:21Z", - "pushed_at": "2024-12-20T13:02:21Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 18 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/7-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/7-r_h_t_forks.json deleted file mode 100644 index 1067cc9089..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/7-r_h_t_forks.json +++ /dev/null @@ -1,312 +0,0 @@ -{ - "id": 906237549, - "node_id": "R_kgDONgQWbQ", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "Alaurant/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:28Z", - "updated_at": "2024-12-20T13:02:28Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/Alaurant/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:Alaurant/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "parent": { - "id": 906237492, - "node_id": "R_kgDONgQWNA", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "hub4j-test-org/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:20Z", - "updated_at": "2024-12-20T13:02:25Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237492, - "node_id": "R_kgDONgQWNA", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "hub4j-test-org/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:20Z", - "updated_at": "2024-12-20T13:02:25Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "network_count": 0, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/8-r_a_temp-testforkdefaultbranchonly.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/8-r_a_temp-testforkdefaultbranchonly.json deleted file mode 100644 index 540be5c247..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/8-r_a_temp-testforkdefaultbranchonly.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "id": 906237549, - "node_id": "R_kgDONgQWbQ", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "Alaurant/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:28Z", - "updated_at": "2024-12-20T13:02:28Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/Alaurant/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:Alaurant/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "parent": { - "id": 906237492, - "node_id": "R_kgDONgQWNA", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "hub4j-test-org/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:20Z", - "updated_at": "2024-12-20T13:02:25Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237492, - "node_id": "R_kgDONgQWNA", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "hub4j-test-org/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:20Z", - "updated_at": "2024-12-20T13:02:25Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "enabled" - }, - "secret_scanning_push_protection": { - "status": "enabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/9-r_a_temp-testforkdefaultbranchonly.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/9-r_a_temp-testforkdefaultbranchonly.json deleted file mode 100644 index 540be5c247..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/__files/9-r_a_temp-testforkdefaultbranchonly.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "id": 906237549, - "node_id": "R_kgDONgQWbQ", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "Alaurant/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:28Z", - "updated_at": "2024-12-20T13:02:28Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/Alaurant/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:Alaurant/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/Alaurant/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "parent": { - "id": 906237492, - "node_id": "R_kgDONgQWNA", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "hub4j-test-org/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:20Z", - "updated_at": "2024-12-20T13:02:25Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237492, - "node_id": "R_kgDONgQWNA", - "name": "temp-testForkDefaultBranchOnly", - "full_name": "hub4j-test-org/temp-testForkDefaultBranchOnly", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "description": "A test repository for testing the github-api project: temp-testForkDefaultBranchOnly", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/deployments", - "created_at": "2024-12-20T13:02:20Z", - "updated_at": "2024-12-20T13:02:25Z", - "pushed_at": "2024-12-20T13:02:27Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkDefaultBranchOnly", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "enabled" - }, - "secret_scanning_push_protection": { - "status": "enabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/1-user.json deleted file mode 100644 index fd54ba4f0d..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "a1f43b65-4451-4893-b3ec-55bb3ed9acb1", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:18 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"385e08560117e426bff1cdeb255753d2813a21fd716dab4fb6fbce27aa60b10f\"", - "Last-Modified": "Sun, 15 Dec 2024 04:04:44 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4583", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "417", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "192D:245A47:15F4196:19D1C40:67656ADA" - } - }, - "uuid": "a1f43b65-4451-4893-b3ec-55bb3ed9acb1", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/10-r_a_t_branches.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/10-r_a_t_branches.json deleted file mode 100644 index f6ca3b4c1b..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/10-r_a_t_branches.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "3a909acd-2013-4517-9a77-1463cf3264ef", - "name": "repos_alaurant_temp-testforkdefaultbranchonly_branches", - "request": { - "url": "/repos/Alaurant/temp-testForkDefaultBranchOnly/branches", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "10-r_a_t_branches.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:34 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"76199ebd0c7fbbf1471460d4f8f4c0840dd2d806b2508d607c954916e56c287b\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4570", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "430", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "195B:2CFAFD:E77421:111939A:67656AE9" - } - }, - "uuid": "3a909acd-2013-4517-9a77-1463cf3264ef", - "persistent": true, - "insertionIndex": 10 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/11-r_a_temp-testforkdefaultbranchonly.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/11-r_a_temp-testforkdefaultbranchonly.json deleted file mode 100644 index 44cd1b71bb..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/11-r_a_temp-testforkdefaultbranchonly.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "f0e6c205-8829-417f-bb6a-9b42277bd227", - "name": "repos_alaurant_temp-testforkdefaultbranchonly", - "request": { - "url": "/repos/Alaurant/temp-testForkDefaultBranchOnly", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:34 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "delete_repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4569", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "431", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "195F:2C3D90:F87165:12348DC:67656AEA" - } - }, - "uuid": "f0e6c205-8829-417f-bb6a-9b42277bd227", - "persistent": true, - "insertionIndex": 11 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/2-r_h_temp-testforkdefaultbranchonly.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/2-r_h_temp-testforkdefaultbranchonly.json deleted file mode 100644 index 7c2fa978cb..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/2-r_h_temp-testforkdefaultbranchonly.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "3a839321-aaa9-4ce2-9d8b-1ea770f6325e", - "name": "repos_hub4j-test-org_temp-testforkdefaultbranchonly", - "request": { - "url": "/repos/hub4j-test-org/temp-testForkDefaultBranchOnly", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_h_temp-testforkdefaultbranchonly.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:25 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"9fb7691cba8fffab330566af72a89dceb7c917597c1de7eb620966055f03e9b9\"", - "Last-Modified": "Fri, 20 Dec 2024 13:02:21 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4578", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "422", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "193E:24DD67:1750018:1B2DB22:67656AE1" - } - }, - "uuid": "3a839321-aaa9-4ce2-9d8b-1ea770f6325e", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/7-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/7-r_h_t_forks.json deleted file mode 100644 index 9c439fc281..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/7-r_h_t_forks.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "id": "e8ef3012-976b-46e8-825d-64021780b138", - "name": "repos_hub4j-test-org_temp-testforkdefaultbranchonly_forks", - "request": { - "url": "/repos/hub4j-test-org/temp-testForkDefaultBranchOnly/forks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"default_branch_only\":true}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 202, - "bodyFileName": "7-r_h_t_forks.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:29 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4573", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "427", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "194C:2CFAFD:E7729D:11191A7:67656AE3" - } - }, - "uuid": "e8ef3012-976b-46e8-825d-64021780b138", - "persistent": true, - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/8-r_a_temp-testforkdefaultbranchonly.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/8-r_a_temp-testforkdefaultbranchonly.json deleted file mode 100644 index 42e6029115..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/8-r_a_temp-testforkdefaultbranchonly.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "id": "68dc53e9-7109-430b-acbd-ee8f0dc8badc", - "name": "repos_alaurant_temp-testforkdefaultbranchonly", - "request": { - "url": "/repos/Alaurant/temp-testForkDefaultBranchOnly", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "8-r_a_temp-testforkdefaultbranchonly.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:30 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"258fe8a9c2265c3f43048484d077b712f4b8bfeed0fe8dca8dbf4bf6dd23cfed\"", - "Last-Modified": "Fri, 20 Dec 2024 13:02:28 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4572", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "428", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1950:2C3D90:F8706A:12347A8:67656AE5" - } - }, - "uuid": "68dc53e9-7109-430b-acbd-ee8f0dc8badc", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-temp-testForkDefaultBranchOnly", - "requiredScenarioState": "Started", - "newScenarioState": "scenario-1-repos-Alaurant-temp-testForkDefaultBranchOnly-2", - "insertionIndex": 8 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/9-r_a_temp-testforkdefaultbranchonly.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/9-r_a_temp-testforkdefaultbranchonly.json deleted file mode 100644 index ee34e7e8bc..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkDefaultBranchOnly/mappings/9-r_a_temp-testforkdefaultbranchonly.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "80a03a5f-1425-4968-bc89-2b44d5ab566f", - "name": "repos_alaurant_temp-testforkdefaultbranchonly", - "request": { - "url": "/repos/Alaurant/temp-testForkDefaultBranchOnly", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "9-r_a_temp-testforkdefaultbranchonly.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:33 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"258fe8a9c2265c3f43048484d077b712f4b8bfeed0fe8dca8dbf4bf6dd23cfed\"", - "Last-Modified": "Fri, 20 Dec 2024 13:02:28 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4571", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "429", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "195A:245A47:15F4535:19D20C9:67656AE9" - } - }, - "uuid": "80a03a5f-1425-4968-bc89-2b44d5ab566f", - "persistent": true, - "scenarioName": "scenario-1-repos-Alaurant-temp-testForkDefaultBranchOnly", - "requiredScenarioState": "scenario-1-repos-Alaurant-temp-testForkDefaultBranchOnly-2", - "insertionIndex": 9 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/1-user.json deleted file mode 100644 index a385d2bfd8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": "Brisbane, AUS", - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 14, - "public_gists": 0, - "followers": 4, - "following": 11, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-12-15T04:04:44Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/10-r_n_temp-testforktoorg.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/10-r_n_temp-testforktoorg.json deleted file mode 100644 index d4a7fe7fc5..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/10-r_n_temp-testforktoorg.json +++ /dev/null @@ -1,363 +0,0 @@ -{ - "id": 906237664, - "node_id": "R_kgDONgQW4A", - "name": "temp-testForkToOrg", - "full_name": "nts-api-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/nts-api-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": true, - "url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:45Z", - "updated_at": "2024-12-20T13:02:45Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/nts-api-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:nts-api-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/nts-api-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/nts-api-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "parent": { - "id": 906237618, - "node_id": "R_kgDONgQWsg", - "name": "temp-testForkToOrg", - "full_name": "hub4j-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:37Z", - "updated_at": "2024-12-20T13:02:42Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237618, - "node_id": "R_kgDONgQWsg", - "name": "temp-testForkToOrg", - "full_name": "hub4j-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:37Z", - "updated_at": "2024-12-20T13:02:42Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/11-r_n_t_branches.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/11-r_n_t_branches.json deleted file mode 100644 index 2996fd47e3..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/11-r_n_t_branches.json +++ /dev/null @@ -1,70 +0,0 @@ -[ - { - "name": "main", - "commit": { - "sha": "41bcbfbf3d7ea68ab3488346ee9b323ac9d2f5ee", - "url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/commits/41bcbfbf3d7ea68ab3488346ee9b323ac9d2f5ee" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/branches/main/protection" - }, - { - "name": "test-branch1", - "commit": { - "sha": "41bcbfbf3d7ea68ab3488346ee9b323ac9d2f5ee", - "url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/commits/41bcbfbf3d7ea68ab3488346ee9b323ac9d2f5ee" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/branches/test-branch1/protection" - }, - { - "name": "test-branch2", - "commit": { - "sha": "41bcbfbf3d7ea68ab3488346ee9b323ac9d2f5ee", - "url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/commits/41bcbfbf3d7ea68ab3488346ee9b323ac9d2f5ee" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/branches/test-branch2/protection" - }, - { - "name": "test-branch3", - "commit": { - "sha": "41bcbfbf3d7ea68ab3488346ee9b323ac9d2f5ee", - "url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/commits/41bcbfbf3d7ea68ab3488346ee9b323ac9d2f5ee" - }, - "protected": false, - "protection": { - "enabled": false, - "required_status_checks": { - "enforcement_level": "off", - "contexts": [], - "checks": [] - } - }, - "protection_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/branches/test-branch3/protection" - } -] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/2-r_h_temp-testforktoorg.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/2-r_h_temp-testforktoorg.json deleted file mode 100644 index bf1c956405..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/2-r_h_temp-testforktoorg.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "id": 906237618, - "node_id": "R_kgDONgQWsg", - "name": "temp-testForkToOrg", - "full_name": "hub4j-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:37Z", - "updated_at": "2024-12-20T13:02:38Z", - "pushed_at": "2024-12-20T13:02:38Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 18 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/7-orgs_nts-api-test-org.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/7-orgs_nts-api-test-org.json deleted file mode 100644 index 6ce9af2a9e..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/7-orgs_nts-api-test-org.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "url": "https://api.github.com/orgs/nts-api-test-org", - "repos_url": "https://api.github.com/orgs/nts-api-test-org/repos", - "events_url": "https://api.github.com/orgs/nts-api-test-org/events", - "hooks_url": "https://api.github.com/orgs/nts-api-test-org/hooks", - "issues_url": "https://api.github.com/orgs/nts-api-test-org/issues", - "members_url": "https://api.github.com/orgs/nts-api-test-org/members{/member}", - "public_members_url": "https://api.github.com/orgs/nts-api-test-org/public_members{/member}", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "description": null, - "is_verified": false, - "has_organization_projects": true, - "has_repository_projects": true, - "public_repos": 5, - "public_gists": 0, - "followers": 0, - "following": 0, - "html_url": "https://github.com/nts-api-test-org", - "created_at": "2024-12-11T07:04:56Z", - "updated_at": "2024-12-11T07:04:56Z", - "archived_at": null, - "type": "Organization", - "total_private_repos": 0, - "owned_private_repos": 0, - "private_gists": 0, - "disk_usage": 0, - "collaborators": 0, - "billing_email": "zhaody085@163.com", - "default_repository_permission": "read", - "members_can_create_repositories": true, - "two_factor_requirement_enabled": false, - "members_allowed_repository_creation_type": "all", - "members_can_create_public_repositories": true, - "members_can_create_private_repositories": true, - "members_can_create_internal_repositories": false, - "members_can_create_pages": true, - "members_can_fork_private_repositories": false, - "web_commit_signoff_required": false, - "deploy_keys_enabled_for_repositories": false, - "members_can_create_public_pages": true, - "members_can_create_private_pages": true, - "plan": { - "name": "free", - "space": 976562499, - "private_repos": 10000, - "filled_seats": 1, - "seats": 0 - }, - "advanced_security_enabled_for_new_repositories": false, - "dependabot_alerts_enabled_for_new_repositories": false, - "dependabot_security_updates_enabled_for_new_repositories": false, - "dependency_graph_enabled_for_new_repositories": false, - "secret_scanning_enabled_for_new_repositories": false, - "secret_scanning_push_protection_enabled_for_new_repositories": false, - "secret_scanning_push_protection_custom_link_enabled": false, - "secret_scanning_push_protection_custom_link": null, - "secret_scanning_validity_checks_enabled": false -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/8-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/8-r_h_t_forks.json deleted file mode 100644 index 09fdc636f2..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/8-r_h_t_forks.json +++ /dev/null @@ -1,334 +0,0 @@ -{ - "id": 906237664, - "node_id": "R_kgDONgQW4A", - "name": "temp-testForkToOrg", - "full_name": "nts-api-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/nts-api-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": true, - "url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:45Z", - "updated_at": "2024-12-20T13:02:45Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/nts-api-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:nts-api-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/nts-api-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/nts-api-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "custom_properties": {}, - "organization": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "parent": { - "id": 906237618, - "node_id": "R_kgDONgQWsg", - "name": "temp-testForkToOrg", - "full_name": "hub4j-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:37Z", - "updated_at": "2024-12-20T13:02:42Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237618, - "node_id": "R_kgDONgQWsg", - "name": "temp-testForkToOrg", - "full_name": "hub4j-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:37Z", - "updated_at": "2024-12-20T13:02:42Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "network_count": 0, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/9-r_n_temp-testforktoorg.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/9-r_n_temp-testforktoorg.json deleted file mode 100644 index d4a7fe7fc5..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/__files/9-r_n_temp-testforktoorg.json +++ /dev/null @@ -1,363 +0,0 @@ -{ - "id": 906237664, - "node_id": "R_kgDONgQW4A", - "name": "temp-testForkToOrg", - "full_name": "nts-api-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/nts-api-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": true, - "url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/nts-api-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:45Z", - "updated_at": "2024-12-20T13:02:45Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/nts-api-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:nts-api-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/nts-api-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/nts-api-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "parent": { - "id": 906237618, - "node_id": "R_kgDONgQWsg", - "name": "temp-testForkToOrg", - "full_name": "hub4j-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:37Z", - "updated_at": "2024-12-20T13:02:42Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237618, - "node_id": "R_kgDONgQWsg", - "name": "temp-testForkToOrg", - "full_name": "hub4j-test-org/temp-testForkToOrg", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "description": "A test repository for testing the github-api project: temp-testForkToOrg", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testForkToOrg/deployments", - "created_at": "2024-12-20T13:02:37Z", - "updated_at": "2024-12-20T13:02:42Z", - "pushed_at": "2024-12-20T13:02:44Z", - "git_url": "git://github.com/hub4j-test-org/temp-testForkToOrg.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testForkToOrg.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testForkToOrg.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testForkToOrg", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/1-user.json deleted file mode 100644 index a84c8478b0..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "c8a7f10c-4fc7-4d26-9788-08099d053a6b", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:36 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"385e08560117e426bff1cdeb255753d2813a21fd716dab4fb6fbce27aa60b10f\"", - "Last-Modified": "Sun, 15 Dec 2024 04:04:44 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4566", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "434", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "196A:2CFAFD:E774A3:1119436:67656AEC" - } - }, - "uuid": "c8a7f10c-4fc7-4d26-9788-08099d053a6b", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/10-r_n_temp-testforktoorg.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/10-r_n_temp-testforktoorg.json deleted file mode 100644 index 75577b75ff..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/10-r_n_temp-testforktoorg.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "83ad8c59-db34-4642-a4bc-2c0ee4c69db1", - "name": "repos_nts-api-test-org_temp-testforktoorg", - "request": { - "url": "/repos/nts-api-test-org/temp-testForkToOrg", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "10-r_n_temp-testforktoorg.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:49 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"18bcfe6236e0f7bd80bbdbd0501ee09516d7de82d0d1623493784d675b63c28a\"", - "Last-Modified": "Fri, 20 Dec 2024 13:02:45 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4553", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "447", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1994:2E6E0F:D826D:109102:67656AF9" - } - }, - "uuid": "83ad8c59-db34-4642-a4bc-2c0ee4c69db1", - "persistent": true, - "scenarioName": "scenario-1-repos-nts-api-test-org-temp-testForkToOrg", - "requiredScenarioState": "scenario-1-repos-nts-api-test-org-temp-testForkToOrg-2", - "insertionIndex": 10 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/11-r_n_t_branches.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/11-r_n_t_branches.json deleted file mode 100644 index db14d66db1..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/11-r_n_t_branches.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "d0c5f80d-b010-4399-a40d-8569cd9ec759", - "name": "repos_nts-api-test-org_temp-testforktoorg_branches", - "request": { - "url": "/repos/nts-api-test-org/temp-testForkToOrg/branches", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "11-r_n_t_branches.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:50 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"581936b81a7edab9b8efb7d06da4a1c1634837d1c5bd2fd75bf1d9adcaea2fa6\"", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4552", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "448", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1995:1F61D2:1660BC6:1A3E840:67656AFA" - } - }, - "uuid": "d0c5f80d-b010-4399-a40d-8569cd9ec759", - "persistent": true, - "insertionIndex": 11 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/12-r_n_temp-testforktoorg.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/12-r_n_temp-testforktoorg.json deleted file mode 100644 index f597accb92..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/12-r_n_temp-testforktoorg.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "id": "ddc73e30-2d80-4c2d-be70-4e5dadf73c39", - "name": "repos_nts-api-test-org_temp-testforktoorg", - "request": { - "url": "/repos/nts-api-test-org/temp-testForkToOrg", - "method": "DELETE", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 204, - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:50 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "delete_repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4551", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "449", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "1996:245A47:15F4938:19D25C0:67656AFA" - } - }, - "uuid": "ddc73e30-2d80-4c2d-be70-4e5dadf73c39", - "persistent": true, - "insertionIndex": 12 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/2-r_h_temp-testforktoorg.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/2-r_h_temp-testforktoorg.json deleted file mode 100644 index 5493958a5c..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/2-r_h_temp-testforktoorg.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "cbdbb4cf-d38c-475b-b74d-278b13ca1012", - "name": "repos_hub4j-test-org_temp-testforktoorg", - "request": { - "url": "/repos/hub4j-test-org/temp-testForkToOrg", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_h_temp-testforktoorg.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:42 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"8b676e0dd05afad713c4b11dfb1c1de9298be89376ed730f84838397c4c8f5c7\"", - "Last-Modified": "Fri, 20 Dec 2024 13:02:38 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4561", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "439", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "197A:24DD67:17503FB:1B2DFF8:67656AF1" - } - }, - "uuid": "cbdbb4cf-d38c-475b-b74d-278b13ca1012", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/7-orgs_nts-api-test-org.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/7-orgs_nts-api-test-org.json deleted file mode 100644 index b0029bc6b8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/7-orgs_nts-api-test-org.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "6eb047bb-0cb7-43d8-b19f-520b915b188b", - "name": "orgs_nts-api-test-org", - "request": { - "url": "/orgs/nts-api-test-org", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "7-orgs_nts-api-test-org.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:44 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"a2d193e9546a2c5ce8c7be65939b8cae828c7028fafacea86617bebee3f18283\"", - "Last-Modified": "Wed, 11 Dec 2024 07:04:56 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "admin:org, read:org, repo, user, write:org", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4556", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "444", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1985:2E6E0F:D8129:108F80:67656AF4" - } - }, - "uuid": "6eb047bb-0cb7-43d8-b19f-520b915b188b", - "persistent": true, - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/8-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/8-r_h_t_forks.json deleted file mode 100644 index b9722bf1aa..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/8-r_h_t_forks.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "id": "cbbf3824-9f52-4861-bbba-ed4ba00a633c", - "name": "repos_hub4j-test-org_temp-testforktoorg_forks", - "request": { - "url": "/repos/hub4j-test-org/temp-testForkToOrg/forks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"organization\":\"nts-api-test-org\"}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 202, - "bodyFileName": "8-r_h_t_forks.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:45 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4555", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "445", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "1986:1F61D2:1660AC7:1A3E6F5:67656AF5" - } - }, - "uuid": "cbbf3824-9f52-4861-bbba-ed4ba00a633c", - "persistent": true, - "insertionIndex": 8 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/9-r_n_temp-testforktoorg.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/9-r_n_temp-testforktoorg.json deleted file mode 100644 index d7a3c17927..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testForkToOrg/mappings/9-r_n_temp-testforktoorg.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "id": "7d2f81fc-56fb-458d-9ba8-8bb0a8c4e8dc", - "name": "repos_nts-api-test-org_temp-testforktoorg", - "request": { - "url": "/repos/nts-api-test-org/temp-testForkToOrg", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "9-r_n_temp-testforktoorg.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:46 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"18bcfe6236e0f7bd80bbdbd0501ee09516d7de82d0d1623493784d675b63c28a\"", - "Last-Modified": "Fri, 20 Dec 2024 13:02:45 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4554", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "446", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "198A:3BD1EB:26F993:2E9519:67656AF5" - } - }, - "uuid": "7d2f81fc-56fb-458d-9ba8-8bb0a8c4e8dc", - "persistent": true, - "scenarioName": "scenario-1-repos-nts-api-test-org-temp-testForkToOrg", - "requiredScenarioState": "Started", - "newScenarioState": "scenario-1-repos-nts-api-test-org-temp-testForkToOrg-2", - "insertionIndex": 9 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/__files/1-user.json deleted file mode 100644 index a385d2bfd8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": "Brisbane, AUS", - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 14, - "public_gists": 0, - "followers": 4, - "following": 11, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-12-15T04:04:44Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/__files/2-r_h_temp-testsleep.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/__files/2-r_h_temp-testsleep.json deleted file mode 100644 index 62b0ea59db..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/__files/2-r_h_temp-testsleep.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "id": 906237707, - "node_id": "R_kgDONgQXCw", - "name": "temp-testSleep", - "full_name": "hub4j-test-org/temp-testSleep", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testSleep", - "description": "A test repository for testing the github-api project: temp-testSleep", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testSleep/deployments", - "created_at": "2024-12-20T13:02:53Z", - "updated_at": "2024-12-20T13:02:57Z", - "pushed_at": "2024-12-20T13:02:53Z", - "git_url": "git://github.com/hub4j-test-org/temp-testSleep.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testSleep.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testSleep.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testSleep", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 18 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/mappings/1-user.json deleted file mode 100644 index 8a5192537b..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "920a33da-4635-4053-b3c8-668f75dbf5b1", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:52 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"385e08560117e426bff1cdeb255753d2813a21fd716dab4fb6fbce27aa60b10f\"", - "Last-Modified": "Sun, 15 Dec 2024 04:04:44 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4548", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "452", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "19A4:1F61D2:1660C42:1A3E8D5:67656AFC" - } - }, - "uuid": "920a33da-4635-4053-b3c8-668f75dbf5b1", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/mappings/2-r_h_temp-testsleep.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/mappings/2-r_h_temp-testsleep.json deleted file mode 100644 index 3c9ca6771f..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testSleep/mappings/2-r_h_temp-testsleep.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "eea96b7f-cbc6-45ef-9401-0588e5e7e57c", - "name": "repos_hub4j-test-org_temp-testsleep", - "request": { - "url": "/repos/hub4j-test-org/temp-testSleep", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_h_temp-testsleep.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:02:57 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"86ebe2844fb2b26815d0bc5bd0b7f5068321ae8266fd34e43caa3663ae7500a9\"", - "Last-Modified": "Fri, 20 Dec 2024 13:02:57 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4543", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "457", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "19B1:139242:13ED1AF:176036E:67656B01" - } - }, - "uuid": "eea96b7f-cbc6-45ef-9401-0588e5e7e57c", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/1-user.json deleted file mode 100644 index a385d2bfd8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": "Brisbane, AUS", - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 14, - "public_gists": 0, - "followers": 4, - "following": 11, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-12-15T04:04:44Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/2-r_h_temp-testtimeoutmessage.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/2-r_h_temp-testtimeoutmessage.json deleted file mode 100644 index a19bd2b1e8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/2-r_h_temp-testtimeoutmessage.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "id": 906238015, - "node_id": "R_kgDONgQYPw", - "name": "temp-testTimeoutMessage", - "full_name": "hub4j-test-org/temp-testTimeoutMessage", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutMessage", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/deployments", - "created_at": "2024-12-20T13:03:45Z", - "updated_at": "2024-12-20T13:03:48Z", - "pushed_at": "2024-12-20T13:03:45Z", - "git_url": "git://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testTimeoutMessage.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 18 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/7-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/7-r_h_t_forks.json deleted file mode 100644 index d035851ade..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/7-r_h_t_forks.json +++ /dev/null @@ -1,312 +0,0 @@ -{ - "id": 906238046, - "node_id": "R_kgDONgQYXg", - "name": "test-message", - "full_name": "Alaurant/test-message", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/test-message", - "description": "A test repository for testing the github-api project: temp-testTimeoutMessage", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/test-message", - "forks_url": "https://api.github.com/repos/Alaurant/test-message/forks", - "keys_url": "https://api.github.com/repos/Alaurant/test-message/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/test-message/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/test-message/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/test-message/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/test-message/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/test-message/events", - "assignees_url": "https://api.github.com/repos/Alaurant/test-message/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/test-message/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/test-message/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/test-message/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/test-message/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/test-message/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/test-message/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/test-message/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/test-message/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/test-message/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/test-message/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/test-message/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/test-message/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/test-message/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/test-message/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/test-message/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/test-message/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/test-message/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/test-message/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/test-message/merges", - "archive_url": "https://api.github.com/repos/Alaurant/test-message/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/test-message/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/test-message/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/test-message/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/test-message/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/test-message/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/test-message/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/test-message/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/test-message/deployments", - "created_at": "2024-12-20T13:03:51Z", - "updated_at": "2024-12-20T13:03:52Z", - "pushed_at": "2024-12-20T13:03:50Z", - "git_url": "git://github.com/Alaurant/test-message.git", - "ssh_url": "git@github.com:Alaurant/test-message.git", - "clone_url": "https://github.com/Alaurant/test-message.git", - "svn_url": "https://github.com/Alaurant/test-message", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "parent": { - "id": 906238015, - "node_id": "R_kgDONgQYPw", - "name": "temp-testTimeoutMessage", - "full_name": "hub4j-test-org/temp-testTimeoutMessage", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutMessage", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/deployments", - "created_at": "2024-12-20T13:03:45Z", - "updated_at": "2024-12-20T13:03:48Z", - "pushed_at": "2024-12-20T13:03:50Z", - "git_url": "git://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testTimeoutMessage.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906238015, - "node_id": "R_kgDONgQYPw", - "name": "temp-testTimeoutMessage", - "full_name": "hub4j-test-org/temp-testTimeoutMessage", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutMessage", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/deployments", - "created_at": "2024-12-20T13:03:45Z", - "updated_at": "2024-12-20T13:03:48Z", - "pushed_at": "2024-12-20T13:03:51Z", - "git_url": "git://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testTimeoutMessage.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "network_count": 0, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/8-r_a_test-message.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/8-r_a_test-message.json deleted file mode 100644 index a33a7e2330..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/__files/8-r_a_test-message.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "id": 906238046, - "node_id": "R_kgDONgQYXg", - "name": "test-message", - "full_name": "Alaurant/test-message", - "private": false, - "owner": { - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/Alaurant/test-message", - "description": "A test repository for testing the github-api project: temp-testTimeoutMessage", - "fork": true, - "url": "https://api.github.com/repos/Alaurant/test-message", - "forks_url": "https://api.github.com/repos/Alaurant/test-message/forks", - "keys_url": "https://api.github.com/repos/Alaurant/test-message/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/Alaurant/test-message/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/Alaurant/test-message/teams", - "hooks_url": "https://api.github.com/repos/Alaurant/test-message/hooks", - "issue_events_url": "https://api.github.com/repos/Alaurant/test-message/issues/events{/number}", - "events_url": "https://api.github.com/repos/Alaurant/test-message/events", - "assignees_url": "https://api.github.com/repos/Alaurant/test-message/assignees{/user}", - "branches_url": "https://api.github.com/repos/Alaurant/test-message/branches{/branch}", - "tags_url": "https://api.github.com/repos/Alaurant/test-message/tags", - "blobs_url": "https://api.github.com/repos/Alaurant/test-message/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/Alaurant/test-message/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/Alaurant/test-message/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/Alaurant/test-message/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/Alaurant/test-message/statuses/{sha}", - "languages_url": "https://api.github.com/repos/Alaurant/test-message/languages", - "stargazers_url": "https://api.github.com/repos/Alaurant/test-message/stargazers", - "contributors_url": "https://api.github.com/repos/Alaurant/test-message/contributors", - "subscribers_url": "https://api.github.com/repos/Alaurant/test-message/subscribers", - "subscription_url": "https://api.github.com/repos/Alaurant/test-message/subscription", - "commits_url": "https://api.github.com/repos/Alaurant/test-message/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/Alaurant/test-message/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/Alaurant/test-message/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/Alaurant/test-message/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/Alaurant/test-message/contents/{+path}", - "compare_url": "https://api.github.com/repos/Alaurant/test-message/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/Alaurant/test-message/merges", - "archive_url": "https://api.github.com/repos/Alaurant/test-message/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/Alaurant/test-message/downloads", - "issues_url": "https://api.github.com/repos/Alaurant/test-message/issues{/number}", - "pulls_url": "https://api.github.com/repos/Alaurant/test-message/pulls{/number}", - "milestones_url": "https://api.github.com/repos/Alaurant/test-message/milestones{/number}", - "notifications_url": "https://api.github.com/repos/Alaurant/test-message/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/Alaurant/test-message/labels{/name}", - "releases_url": "https://api.github.com/repos/Alaurant/test-message/releases{/id}", - "deployments_url": "https://api.github.com/repos/Alaurant/test-message/deployments", - "created_at": "2024-12-20T13:03:51Z", - "updated_at": "2024-12-20T13:03:52Z", - "pushed_at": "2024-12-20T13:03:50Z", - "git_url": "git://github.com/Alaurant/test-message.git", - "ssh_url": "git@github.com:Alaurant/test-message.git", - "clone_url": "https://github.com/Alaurant/test-message.git", - "svn_url": "https://github.com/Alaurant/test-message", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "parent": { - "id": 906238015, - "node_id": "R_kgDONgQYPw", - "name": "temp-testTimeoutMessage", - "full_name": "hub4j-test-org/temp-testTimeoutMessage", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutMessage", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/deployments", - "created_at": "2024-12-20T13:03:45Z", - "updated_at": "2024-12-20T13:03:48Z", - "pushed_at": "2024-12-20T13:03:51Z", - "git_url": "git://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testTimeoutMessage.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906238015, - "node_id": "R_kgDONgQYPw", - "name": "temp-testTimeoutMessage", - "full_name": "hub4j-test-org/temp-testTimeoutMessage", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutMessage", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutMessage/deployments", - "created_at": "2024-12-20T13:03:45Z", - "updated_at": "2024-12-20T13:03:48Z", - "pushed_at": "2024-12-20T13:03:51Z", - "git_url": "git://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testTimeoutMessage.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testTimeoutMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "security_and_analysis": { - "secret_scanning": { - "status": "enabled" - }, - "secret_scanning_push_protection": { - "status": "enabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 1, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/1-user.json deleted file mode 100644 index c4d20025e3..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "ec8a0b27-5d8c-445c-9e00-0525603e6dff", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:43 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"385e08560117e426bff1cdeb255753d2813a21fd716dab4fb6fbce27aa60b10f\"", - "Last-Modified": "Sun, 15 Dec 2024 04:04:44 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4487", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "513", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1861:32E7C9:14E692D:187C22E:67656B2F" - } - }, - "uuid": "ec8a0b27-5d8c-445c-9e00-0525603e6dff", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/2-r_h_temp-testtimeoutmessage.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/2-r_h_temp-testtimeoutmessage.json deleted file mode 100644 index 877814016f..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/2-r_h_temp-testtimeoutmessage.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "e8659a91-fe4e-4444-8b49-2bad02689ffe", - "name": "repos_hub4j-test-org_temp-testtimeoutmessage", - "request": { - "url": "/repos/hub4j-test-org/temp-testTimeoutMessage", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_h_temp-testtimeoutmessage.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:49 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"56ea75b5d16128b494b9d90ed5dcc3b6217ed8948ebc17b00604aba01ca2a55d\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:48 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4482", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "518", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "186E:27FAA5:578049:68006F:67656B35" - } - }, - "uuid": "e8659a91-fe4e-4444-8b49-2bad02689ffe", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/7-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/7-r_h_t_forks.json deleted file mode 100644 index bb27e7597f..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/7-r_h_t_forks.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "id": "0a5273fe-ee5d-43c3-b6c9-be91be770726", - "name": "repos_hub4j-test-org_temp-testtimeoutmessage_forks", - "request": { - "url": "/repos/hub4j-test-org/temp-testTimeoutMessage/forks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"name\":\"test-message\"}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 202, - "bodyFileName": "7-r_h_t_forks.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:52 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4477", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "523", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "187B:2C3D90:F887C7:12363DA:67656B37" - } - }, - "uuid": "0a5273fe-ee5d-43c3-b6c9-be91be770726", - "persistent": true, - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/8-r_a_test-message.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/8-r_a_test-message.json deleted file mode 100644 index fa201a1743..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutMessage/mappings/8-r_a_test-message.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "dc4377aa-727f-42c9-b91e-6ef5c92826da", - "name": "repos_alaurant_test-message", - "request": { - "url": "/repos/Alaurant/test-message", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 404, - "body": "{\"message\":\"Not Found\",\"documentation_url\":\"https://docs.github.com/rest/reference/repos#get-a-repository\"}", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:53 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"897c68bbc417e21f9fd33fe6a2eee4d9abafcaaf6d920fbe747fa7d53410af47\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:52 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4476", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "524", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "187F:32E7C9:14E6BD1:187C555:67656B38" - } - }, - "uuid": "dc4377aa-727f-42c9-b91e-6ef5c92826da", - "persistent": true, - "insertionIndex": 8 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/1-user.json deleted file mode 100644 index a385d2bfd8..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": "Brisbane, AUS", - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 14, - "public_gists": 0, - "followers": 4, - "following": 11, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-12-15T04:04:44Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/2-r_h_temp-testtimeoutorgmessage.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/2-r_h_temp-testtimeoutorgmessage.json deleted file mode 100644 index c6bff04068..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/2-r_h_temp-testtimeoutorgmessage.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "id": 906237854, - "node_id": "R_kgDONgQXng", - "name": "temp-testTimeoutOrgMessage", - "full_name": "hub4j-test-org/temp-testTimeoutOrgMessage", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutOrgMessage", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/deployments", - "created_at": "2024-12-20T13:03:18Z", - "updated_at": "2024-12-20T13:03:18Z", - "pushed_at": "2024-12-20T13:03:18Z", - "git_url": "git://github.com/hub4j-test-org/temp-testTimeoutOrgMessage.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testTimeoutOrgMessage.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 18 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/7-orgs_nts-api-test-org.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/7-orgs_nts-api-test-org.json deleted file mode 100644 index 6ce9af2a9e..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/7-orgs_nts-api-test-org.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "url": "https://api.github.com/orgs/nts-api-test-org", - "repos_url": "https://api.github.com/orgs/nts-api-test-org/repos", - "events_url": "https://api.github.com/orgs/nts-api-test-org/events", - "hooks_url": "https://api.github.com/orgs/nts-api-test-org/hooks", - "issues_url": "https://api.github.com/orgs/nts-api-test-org/issues", - "members_url": "https://api.github.com/orgs/nts-api-test-org/members{/member}", - "public_members_url": "https://api.github.com/orgs/nts-api-test-org/public_members{/member}", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "description": null, - "is_verified": false, - "has_organization_projects": true, - "has_repository_projects": true, - "public_repos": 5, - "public_gists": 0, - "followers": 0, - "following": 0, - "html_url": "https://github.com/nts-api-test-org", - "created_at": "2024-12-11T07:04:56Z", - "updated_at": "2024-12-11T07:04:56Z", - "archived_at": null, - "type": "Organization", - "total_private_repos": 0, - "owned_private_repos": 0, - "private_gists": 0, - "disk_usage": 0, - "collaborators": 0, - "billing_email": "zhaody085@163.com", - "default_repository_permission": "read", - "members_can_create_repositories": true, - "two_factor_requirement_enabled": false, - "members_allowed_repository_creation_type": "all", - "members_can_create_public_repositories": true, - "members_can_create_private_repositories": true, - "members_can_create_internal_repositories": false, - "members_can_create_pages": true, - "members_can_fork_private_repositories": false, - "web_commit_signoff_required": false, - "deploy_keys_enabled_for_repositories": false, - "members_can_create_public_pages": true, - "members_can_create_private_pages": true, - "plan": { - "name": "free", - "space": 976562499, - "private_repos": 10000, - "filled_seats": 1, - "seats": 0 - }, - "advanced_security_enabled_for_new_repositories": false, - "dependabot_alerts_enabled_for_new_repositories": false, - "dependabot_security_updates_enabled_for_new_repositories": false, - "dependency_graph_enabled_for_new_repositories": false, - "secret_scanning_enabled_for_new_repositories": false, - "secret_scanning_push_protection_enabled_for_new_repositories": false, - "secret_scanning_push_protection_custom_link_enabled": false, - "secret_scanning_push_protection_custom_link": null, - "secret_scanning_validity_checks_enabled": false -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/8-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/8-r_h_t_forks.json deleted file mode 100644 index 74f4626f79..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/8-r_h_t_forks.json +++ /dev/null @@ -1,334 +0,0 @@ -{ - "id": 906237909, - "node_id": "R_kgDONgQX1Q", - "name": "temp-testTimeoutOrgMessage-2", - "full_name": "nts-api-test-org/temp-testTimeoutOrgMessage-2", - "private": false, - "owner": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/nts-api-test-org/temp-testTimeoutOrgMessage-2", - "description": "A test repository for testing the github-api project: temp-testTimeoutOrgMessage", - "fork": true, - "url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2", - "forks_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/forks", - "keys_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/teams", - "hooks_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/hooks", - "issue_events_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/issues/events{/number}", - "events_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/events", - "assignees_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/assignees{/user}", - "branches_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/branches{/branch}", - "tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/tags", - "blobs_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/statuses/{sha}", - "languages_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/languages", - "stargazers_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/stargazers", - "contributors_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/contributors", - "subscribers_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/subscribers", - "subscription_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/subscription", - "commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/contents/{+path}", - "compare_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/merges", - "archive_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/downloads", - "issues_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/issues{/number}", - "pulls_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/pulls{/number}", - "milestones_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/milestones{/number}", - "notifications_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/labels{/name}", - "releases_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/releases{/id}", - "deployments_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage-2/deployments", - "created_at": "2024-12-20T13:03:25Z", - "updated_at": "2024-12-20T13:03:25Z", - "pushed_at": "2024-12-20T13:03:24Z", - "git_url": "git://github.com/nts-api-test-org/temp-testTimeoutOrgMessage-2.git", - "ssh_url": "git@github.com:nts-api-test-org/temp-testTimeoutOrgMessage-2.git", - "clone_url": "https://github.com/nts-api-test-org/temp-testTimeoutOrgMessage-2.git", - "svn_url": "https://github.com/nts-api-test-org/temp-testTimeoutOrgMessage-2", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "custom_properties": {}, - "organization": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "parent": { - "id": 906237854, - "node_id": "R_kgDONgQXng", - "name": "temp-testTimeoutOrgMessage", - "full_name": "hub4j-test-org/temp-testTimeoutOrgMessage", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutOrgMessage", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/deployments", - "created_at": "2024-12-20T13:03:18Z", - "updated_at": "2024-12-20T13:03:22Z", - "pushed_at": "2024-12-20T13:03:24Z", - "git_url": "git://github.com/hub4j-test-org/temp-testTimeoutOrgMessage.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testTimeoutOrgMessage.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 1, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 1, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "source": { - "id": 906237854, - "node_id": "R_kgDONgQXng", - "name": "temp-testTimeoutOrgMessage", - "full_name": "hub4j-test-org/temp-testTimeoutOrgMessage", - "private": false, - "owner": { - "login": "hub4j-test-org", - "id": 7544739, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=", - "avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j-test-org", - "html_url": "https://github.com/hub4j-test-org", - "followers_url": "https://api.github.com/users/hub4j-test-org/followers", - "following_url": "https://api.github.com/users/hub4j-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j-test-org/orgs", - "repos_url": "https://api.github.com/users/hub4j-test-org/repos", - "events_url": "https://api.github.com/users/hub4j-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutOrgMessage", - "fork": false, - "url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage", - "forks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/forks", - "keys_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/teams", - "hooks_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/events", - "assignees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/tags", - "blobs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/languages", - "stargazers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/contributors", - "subscribers_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/subscription", - "commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/merges", - "archive_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/downloads", - "issues_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j-test-org/temp-testTimeoutOrgMessage/deployments", - "created_at": "2024-12-20T13:03:18Z", - "updated_at": "2024-12-20T13:03:22Z", - "pushed_at": "2024-12-20T13:03:24Z", - "git_url": "git://github.com/hub4j-test-org/temp-testTimeoutOrgMessage.git", - "ssh_url": "git@github.com:hub4j-test-org/temp-testTimeoutOrgMessage.git", - "clone_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage.git", - "svn_url": "https://github.com/hub4j-test-org/temp-testTimeoutOrgMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main" - }, - "network_count": 0, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/9-r_n_temp-testtimeoutorgmessage.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/9-r_n_temp-testtimeoutorgmessage.json deleted file mode 100644 index f7ae382e60..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/__files/9-r_n_temp-testtimeoutorgmessage.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "id": 906230271, - "node_id": "R_kgDONgP5_w", - "name": "temp-testTimeoutOrgMessage", - "full_name": "nts-api-test-org/temp-testTimeoutOrgMessage", - "private": false, - "owner": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "html_url": "https://github.com/nts-api-test-org/temp-testTimeoutOrgMessage", - "description": "A test repository for testing the github-api project: temp-testTimeoutOrgMessage", - "fork": false, - "url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage", - "forks_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/forks", - "keys_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/teams", - "hooks_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/hooks", - "issue_events_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/issues/events{/number}", - "events_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/events", - "assignees_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/assignees{/user}", - "branches_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/branches{/branch}", - "tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/tags", - "blobs_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/statuses/{sha}", - "languages_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/languages", - "stargazers_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/stargazers", - "contributors_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/contributors", - "subscribers_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/subscribers", - "subscription_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/subscription", - "commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/contents/{+path}", - "compare_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/merges", - "archive_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/downloads", - "issues_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/issues{/number}", - "pulls_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/pulls{/number}", - "milestones_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/milestones{/number}", - "notifications_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/labels{/name}", - "releases_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/releases{/id}", - "deployments_url": "https://api.github.com/repos/nts-api-test-org/temp-testTimeoutOrgMessage/deployments", - "created_at": "2024-12-20T12:43:24Z", - "updated_at": "2024-12-20T12:43:24Z", - "pushed_at": "2024-12-20T12:43:23Z", - "git_url": "git://github.com/nts-api-test-org/temp-testTimeoutOrgMessage.git", - "ssh_url": "git@github.com:nts-api-test-org/temp-testTimeoutOrgMessage.git", - "clone_url": "https://github.com/nts-api-test-org/temp-testTimeoutOrgMessage.git", - "svn_url": "https://github.com/nts-api-test-org/temp-testTimeoutOrgMessage", - "homepage": "http://github-api.kohsuke.org/", - "size": 0, - "stargazers_count": 0, - "watchers_count": 0, - "language": null, - "has_issues": false, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": false, - "has_discussions": false, - "forks_count": 0, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 0, - "license": null, - "allow_forking": true, - "is_template": false, - "web_commit_signoff_required": false, - "topics": [], - "visibility": "public", - "forks": 0, - "open_issues": 0, - "watchers": 0, - "default_branch": "main", - "permissions": { - "admin": true, - "maintain": true, - "push": true, - "triage": true, - "pull": true - }, - "temp_clone_token": "", - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "allow_auto_merge": false, - "delete_branch_on_merge": false, - "allow_update_branch": false, - "use_squash_pr_title_as_default": false, - "squash_merge_commit_message": "COMMIT_MESSAGES", - "squash_merge_commit_title": "COMMIT_OR_PR_TITLE", - "merge_commit_message": "PR_TITLE", - "merge_commit_title": "MERGE_MESSAGE", - "custom_properties": {}, - "organization": { - "login": "nts-api-test-org", - "id": 191328158, - "node_id": "O_kgDOC2dvng", - "avatar_url": "https://avatars.githubusercontent.com/u/191328158?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/nts-api-test-org", - "html_url": "https://github.com/nts-api-test-org", - "followers_url": "https://api.github.com/users/nts-api-test-org/followers", - "following_url": "https://api.github.com/users/nts-api-test-org/following{/other_user}", - "gists_url": "https://api.github.com/users/nts-api-test-org/gists{/gist_id}", - "starred_url": "https://api.github.com/users/nts-api-test-org/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/nts-api-test-org/subscriptions", - "organizations_url": "https://api.github.com/users/nts-api-test-org/orgs", - "repos_url": "https://api.github.com/users/nts-api-test-org/repos", - "events_url": "https://api.github.com/users/nts-api-test-org/events{/privacy}", - "received_events_url": "https://api.github.com/users/nts-api-test-org/received_events", - "type": "Organization", - "user_view_type": "public", - "site_admin": false - }, - "security_and_analysis": { - "secret_scanning": { - "status": "disabled" - }, - "secret_scanning_push_protection": { - "status": "disabled" - }, - "dependabot_security_updates": { - "status": "disabled" - }, - "secret_scanning_non_provider_patterns": { - "status": "disabled" - }, - "secret_scanning_validity_checks": { - "status": "disabled" - } - }, - "network_count": 0, - "subscribers_count": 0 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/1-user.json deleted file mode 100644 index 6bd90c04ee..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "ebd5332a-d8a9-4cfc-acec-aac3c3df337d", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:16 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"385e08560117e426bff1cdeb255753d2813a21fd716dab4fb6fbce27aa60b10f\"", - "Last-Modified": "Sun, 15 Dec 2024 04:04:44 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4519", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "481", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "17FD:24DD67:1750CD9:1B2EAF3:67656B14" - } - }, - "uuid": "ebd5332a-d8a9-4cfc-acec-aac3c3df337d", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/2-r_h_temp-testtimeoutorgmessage.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/2-r_h_temp-testtimeoutorgmessage.json deleted file mode 100644 index f65cf8646c..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/2-r_h_temp-testtimeoutorgmessage.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "6fb39171-0d03-4034-b599-d997a13e1c23", - "name": "repos_hub4j-test-org_temp-testtimeoutorgmessage", - "request": { - "url": "/repos/hub4j-test-org/temp-testTimeoutOrgMessage", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-r_h_temp-testtimeoutorgmessage.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:22 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"7378a59c2455bdcbe4d4476a907a49e1404a321cf5c489fbe7f920f48e57a719\"", - "Last-Modified": "Fri, 20 Dec 2024 13:03:18 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4514", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "486", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "180D:245A47:15F5177:19D2FEB:67656B1A" - } - }, - "uuid": "6fb39171-0d03-4034-b599-d997a13e1c23", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/7-orgs_nts-api-test-org.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/7-orgs_nts-api-test-org.json deleted file mode 100644 index 787ad120aa..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/7-orgs_nts-api-test-org.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "d6996ef4-8737-41a7-a8ea-154b34e6dccb", - "name": "orgs_nts-api-test-org", - "request": { - "url": "/orgs/nts-api-test-org", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "7-orgs_nts-api-test-org.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:25 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"a2d193e9546a2c5ce8c7be65939b8cae828c7028fafacea86617bebee3f18283\"", - "Last-Modified": "Wed, 11 Dec 2024 07:04:56 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "admin:org, read:org, repo, user, write:org", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4509", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "491", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1818:4C45C:179A3D7:1B78284:67656B1C" - } - }, - "uuid": "d6996ef4-8737-41a7-a8ea-154b34e6dccb", - "persistent": true, - "insertionIndex": 7 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/8-r_h_t_forks.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/8-r_h_t_forks.json deleted file mode 100644 index 38d55d277c..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/8-r_h_t_forks.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "id": "7d927adc-c6ad-473d-b682-9d3ec2b9022a", - "name": "repos_hub4j-test-org_temp-testtimeoutorgmessage_forks", - "request": { - "url": "/repos/hub4j-test-org/temp-testTimeoutOrgMessage/forks", - "method": "POST", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - }, - "bodyPatterns": [ - { - "equalToJson": "{\"organization\":\"nts-api-test-org\"}", - "ignoreArrayOrder": true, - "ignoreExtraElements": false - } - ] - }, - "response": { - "status": 202, - "bodyFileName": "8-r_h_t_forks.json", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:25 GMT", - "Content-Type": "application/json; charset=utf-8", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4508", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "492", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Vary": "Accept-Encoding, Accept, X-Requested-With", - "Server": "github.com", - "X-GitHub-Request-Id": "1819:139242:13EDB7B:1760EE9:67656B1D" - } - }, - "uuid": "7d927adc-c6ad-473d-b682-9d3ec2b9022a", - "persistent": true, - "insertionIndex": 8 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/9-r_n_temp-testtimeoutorgmessage.json b/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/9-r_n_temp-testtimeoutorgmessage.json deleted file mode 100644 index 7e0b630b37..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryForkBuilderTest/wiremock/testTimeoutOrgMessage/mappings/9-r_n_temp-testtimeoutorgmessage.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "e56316fc-1257-4501-ac91-b1e08369f523", - "name": "repos_nts-api-test-org_temp-testtimeoutorgmessage", - "request": { - "url": "/repos/nts-api-test-org/temp-testTimeoutOrgMessage", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 404, - "body": "{\"message\":\"Not Found\",\"documentation_url\":\"https://docs.github.com/rest/reference/repos#get-a-repository\"}", - "headers": { - "Date": "Fri, 20 Dec 2024 13:03:26 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"da073a61f98b326c509ca90e3f9423a2c3c6fcc816e0146fdb19804a400adaae\"", - "Last-Modified": "Fri, 20 Dec 2024 12:43:24 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4507", - "X-RateLimit-Reset": "1734700582", - "X-RateLimit-Used": "493", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "181D:2CFAFD:E7811E:111A3A5:67656B1E" - } - }, - "uuid": "e56316fc-1257-4501-ac91-b1e08369f523", - "persistent": true, - "insertionIndex": 9 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/1-user.json deleted file mode 100644 index 39d6c8353e..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/1-user.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "login": "bitwiseman", - "id": 1958953, - "node_id": "MDQ6VXNlcjE5NTg5NTM=", - "avatar_url": "https://avatars3.githubusercontent.com/u/1958953?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/bitwiseman", - "html_url": "https://github.com/bitwiseman", - "followers_url": "https://api.github.com/users/bitwiseman/followers", - "following_url": "https://api.github.com/users/bitwiseman/following{/other_user}", - "gists_url": "https://api.github.com/users/bitwiseman/gists{/gist_id}", - "starred_url": "https://api.github.com/users/bitwiseman/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/bitwiseman/subscriptions", - "organizations_url": "https://api.github.com/users/bitwiseman/orgs", - "repos_url": "https://api.github.com/users/bitwiseman/repos", - "events_url": "https://api.github.com/users/bitwiseman/events{/privacy}", - "received_events_url": "https://api.github.com/users/bitwiseman/received_events", - "type": "User", - "site_admin": false, - "name": "Liam Newman", - "company": "Cloudbees, Inc.", - "blog": "", - "location": "Seattle, WA, USA", - "email": "bitwiseman@gmail.com", - "hireable": null, - "bio": "https://twitter.com/bitwiseman", - "public_repos": 167, - "public_gists": 4, - "followers": 136, - "following": 9, - "created_at": "2012-07-11T20:38:33Z", - "updated_at": "2019-09-24T19:32:29Z", - "private_gists": 7, - "total_private_repos": 9, - "owned_private_repos": 0, - "disk_usage": 33697, - "collaborators": 0, - "two_factor_authentication": true, - "plan": { - "name": "free", - "space": 976562499, - "collaborators": 0, - "private_repos": 10000 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/10-users_kohsuke.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/10-users_kohsuke.json deleted file mode 100644 index b0bb3da441..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/10-users_kohsuke.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "login": "kohsuke", - "id": 50003, - "node_id": "MDQ6VXNlcjUwMDAz", - "avatar_url": "https://avatars.githubusercontent.com/u/50003?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/kohsuke", - "html_url": "https://github.com/kohsuke", - "followers_url": "https://api.github.com/users/kohsuke/followers", - "following_url": "https://api.github.com/users/kohsuke/following{/other_user}", - "gists_url": "https://api.github.com/users/kohsuke/gists{/gist_id}", - "starred_url": "https://api.github.com/users/kohsuke/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/kohsuke/subscriptions", - "organizations_url": "https://api.github.com/users/kohsuke/orgs", - "repos_url": "https://api.github.com/users/kohsuke/repos", - "events_url": "https://api.github.com/users/kohsuke/events{/privacy}", - "received_events_url": "https://api.github.com/users/kohsuke/received_events", - "type": "User", - "site_admin": false, - "name": "Kohsuke Kawaguchi", - "company": "@launchableinc ", - "blog": "https://www.kohsuke.org/", - "location": "San Jose, California", - "email": "kk@kohsuke.org", - "hireable": null, - "bio": null, - "twitter_username": null, - "public_repos": 265, - "public_gists": 113, - "followers": 1999, - "following": 3, - "created_at": "2009-01-28T18:53:21Z", - "updated_at": "2022-04-10T22:58:15Z" -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/2-orgs_hub4j.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/2-orgs_hub4j.json deleted file mode 100644 index 2efefa017a..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/2-orgs_hub4j.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "login": "hub4j", - "id": 54909825, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjU0OTA5ODI1", - "url": "https://api.github.com/orgs/hub4j", - "repos_url": "https://api.github.com/orgs/hub4j/repos", - "events_url": "https://api.github.com/orgs/hub4j/events", - "hooks_url": "https://api.github.com/orgs/hub4j/hooks", - "issues_url": "https://api.github.com/orgs/hub4j/issues", - "members_url": "https://api.github.com/orgs/hub4j/members{/member}", - "public_members_url": "https://api.github.com/orgs/hub4j/public_members{/member}", - "avatar_url": "https://avatars3.githubusercontent.com/u/54909825?v=4", - "description": null, - "is_verified": false, - "has_organization_projects": true, - "has_repository_projects": true, - "public_repos": 1, - "public_gists": 0, - "followers": 0, - "following": 0, - "html_url": "https://github.com/hub4j", - "created_at": "2019-09-04T18:12:34Z", - "updated_at": "2019-09-04T18:12:34Z", - "type": "Organization", - "total_private_repos": 0, - "owned_private_repos": 0, - "private_gists": 0, - "disk_usage": 11899, - "collaborators": 0, - "billing_email": "bitwiseman@gmail.com", - "default_repository_permission": "read", - "members_can_create_repositories": true, - "two_factor_requirement_enabled": false, - "plan": { - "name": "free", - "space": 976562499, - "private_repos": 0, - "filled_seats": 2, - "seats": 0 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/3-r_h_github-api.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/3-r_h_github-api.json deleted file mode 100644 index a832870b2d..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/3-r_h_github-api.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "id": 617210, - "node_id": "MDEwOlJlcG9zaXRvcnk2MTcyMTA=", - "name": "github-api", - "full_name": "hub4j/github-api", - "private": false, - "owner": { - "login": "hub4j", - "id": 54909825, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjU0OTA5ODI1", - "avatar_url": "https://avatars3.githubusercontent.com/u/54909825?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j", - "html_url": "https://github.com/hub4j", - "followers_url": "https://api.github.com/users/hub4j/followers", - "following_url": "https://api.github.com/users/hub4j/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j/orgs", - "repos_url": "https://api.github.com/users/hub4j/repos", - "events_url": "https://api.github.com/users/hub4j/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j/received_events", - "type": "Organization", - "site_admin": false - }, - "html_url": "https://github.com/hub4j/github-api", - "description": "Java API for GitHub", - "fork": false, - "url": "https://api.github.com/repos/hub4j/github-api", - "forks_url": "https://api.github.com/repos/hub4j/github-api/forks", - "keys_url": "https://api.github.com/repos/hub4j/github-api/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/hub4j/github-api/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/hub4j/github-api/teams", - "hooks_url": "https://api.github.com/repos/hub4j/github-api/hooks", - "issue_events_url": "https://api.github.com/repos/hub4j/github-api/issues/events{/number}", - "events_url": "https://api.github.com/repos/hub4j/github-api/events", - "assignees_url": "https://api.github.com/repos/hub4j/github-api/assignees{/user}", - "branches_url": "https://api.github.com/repos/hub4j/github-api/branches{/branch}", - "tags_url": "https://api.github.com/repos/hub4j/github-api/tags", - "blobs_url": "https://api.github.com/repos/hub4j/github-api/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/hub4j/github-api/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/hub4j/github-api/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/hub4j/github-api/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/hub4j/github-api/statuses/{sha}", - "languages_url": "https://api.github.com/repos/hub4j/github-api/languages", - "stargazers_url": "https://api.github.com/repos/hub4j/github-api/stargazers", - "contributors_url": "https://api.github.com/repos/hub4j/github-api/contributors?anon=true", - "subscribers_url": "https://api.github.com/repos/hub4j/github-api/subscribers", - "subscription_url": "https://api.github.com/repos/hub4j/github-api/subscription", - "commits_url": "https://api.github.com/repos/hub4j/github-api/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/hub4j/github-api/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/hub4j/github-api/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/hub4j/github-api/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/hub4j/github-api/contents/{+path}", - "compare_url": "https://api.github.com/repos/hub4j/github-api/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/hub4j/github-api/merges", - "archive_url": "https://api.github.com/repos/hub4j/github-api/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/hub4j/github-api/downloads", - "issues_url": "https://api.github.com/repos/hub4j/github-api/issues{/number}", - "pulls_url": "https://api.github.com/repos/hub4j/github-api/pulls{/number}", - "milestones_url": "https://api.github.com/repos/hub4j/github-api/milestones{/number}", - "notifications_url": "https://api.github.com/repos/hub4j/github-api/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/hub4j/github-api/labels{/name}", - "releases_url": "https://api.github.com/repos/hub4j/github-api/releases{/id}", - "deployments_url": "https://api.github.com/repos/hub4j/github-api/deployments", - "created_at": "2010-04-19T04:13:03Z", - "updated_at": "2019-10-03T09:41:10Z", - "pushed_at": "2019-10-02T22:27:45Z", - "git_url": "git://github.com/hub4j/github-api.git", - "ssh_url": "git@github.com:hub4j/github-api.git", - "clone_url": "https://github.com/hub4j/github-api.git", - "svn_url": "https://github.com/hub4j/github-api", - "homepage": "http://github-api.kohsuke.org/", - "size": 11899, - "stargazers_count": 557, - "watchers_count": 557, - "language": "Java", - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": true, - "has_pages": true, - "forks_count": 428, - "mirror_url": null, - "archived": false, - "disabled": false, - "open_issues_count": 90, - "license": { - "key": "mit", - "name": "MIT License", - "spdx_id": "MIT", - "url": "https://api.github.com/licenses/mit", - "node_id": "MDc6TGljZW5zZTEz" - }, - "forks": 428, - "open_issues": 90, - "watchers": 557, - "default_branch": "main", - "permissions": { - "admin": true, - "push": true, - "pull": true - }, - "allow_squash_merge": true, - "allow_merge_commit": true, - "allow_rebase_merge": true, - "organization": { - "login": "hub4j", - "id": 54909825, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjU0OTA5ODI1", - "avatar_url": "https://avatars3.githubusercontent.com/u/54909825?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/hub4j", - "html_url": "https://github.com/hub4j", - "followers_url": "https://api.github.com/users/hub4j/followers", - "following_url": "https://api.github.com/users/hub4j/following{/other_user}", - "gists_url": "https://api.github.com/users/hub4j/gists{/gist_id}", - "starred_url": "https://api.github.com/users/hub4j/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/hub4j/subscriptions", - "organizations_url": "https://api.github.com/users/hub4j/orgs", - "repos_url": "https://api.github.com/users/hub4j/repos", - "events_url": "https://api.github.com/users/hub4j/events{/privacy}", - "received_events_url": "https://api.github.com/users/hub4j/received_events", - "type": "Organization", - "site_admin": false - }, - "network_count": 428, - "subscribers_count": 50 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/4-r_h_g_contributors.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/4-r_h_g_contributors.json deleted file mode 100644 index b2c2b6c819..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/__files/4-r_h_g_contributors.json +++ /dev/null @@ -1,638 +0,0 @@ -[ - { - "email":"joebob@example.org", - "name":"Joseph Roberts", - "type":"Anonymous", - "contributions":3 - }, - { - "login": "kohsuke", - "id": 50003, - "node_id": "MDQ6VXNlcjUwMDAz", - "avatar_url": "https://avatars1.githubusercontent.com/u/50003?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/kohsuke", - "html_url": "https://github.com/kohsuke", - "followers_url": "https://api.github.com/users/kohsuke/followers", - "following_url": "https://api.github.com/users/kohsuke/following{/other_user}", - "gists_url": "https://api.github.com/users/kohsuke/gists{/gist_id}", - "starred_url": "https://api.github.com/users/kohsuke/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/kohsuke/subscriptions", - "organizations_url": "https://api.github.com/users/kohsuke/orgs", - "repos_url": "https://api.github.com/users/kohsuke/repos", - "events_url": "https://api.github.com/users/kohsuke/events{/privacy}", - "received_events_url": "https://api.github.com/users/kohsuke/received_events", - "type": "User", - "site_admin": false, - "contributions": 892 - }, - { - "login": "bitwiseman", - "id": 1958953, - "node_id": "MDQ6VXNlcjE5NTg5NTM=", - "avatar_url": "https://avatars3.githubusercontent.com/u/1958953?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/bitwiseman", - "html_url": "https://github.com/bitwiseman", - "followers_url": "https://api.github.com/users/bitwiseman/followers", - "following_url": "https://api.github.com/users/bitwiseman/following{/other_user}", - "gists_url": "https://api.github.com/users/bitwiseman/gists{/gist_id}", - "starred_url": "https://api.github.com/users/bitwiseman/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/bitwiseman/subscriptions", - "organizations_url": "https://api.github.com/users/bitwiseman/orgs", - "repos_url": "https://api.github.com/users/bitwiseman/repos", - "events_url": "https://api.github.com/users/bitwiseman/events{/privacy}", - "received_events_url": "https://api.github.com/users/bitwiseman/received_events", - "type": "User", - "site_admin": false, - "contributions": 84 - }, - { - "login": "stephenc", - "id": 209336, - "node_id": "MDQ6VXNlcjIwOTMzNg==", - "avatar_url": "https://avatars2.githubusercontent.com/u/209336?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/stephenc", - "html_url": "https://github.com/stephenc", - "followers_url": "https://api.github.com/users/stephenc/followers", - "following_url": "https://api.github.com/users/stephenc/following{/other_user}", - "gists_url": "https://api.github.com/users/stephenc/gists{/gist_id}", - "starred_url": "https://api.github.com/users/stephenc/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/stephenc/subscriptions", - "organizations_url": "https://api.github.com/users/stephenc/orgs", - "repos_url": "https://api.github.com/users/stephenc/repos", - "events_url": "https://api.github.com/users/stephenc/events{/privacy}", - "received_events_url": "https://api.github.com/users/stephenc/received_events", - "type": "User", - "site_admin": false, - "contributions": 21 - }, - { - "login": "janinko", - "id": 644267, - "node_id": "MDQ6VXNlcjY0NDI2Nw==", - "avatar_url": "https://avatars2.githubusercontent.com/u/644267?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/janinko", - "html_url": "https://github.com/janinko", - "followers_url": "https://api.github.com/users/janinko/followers", - "following_url": "https://api.github.com/users/janinko/following{/other_user}", - "gists_url": "https://api.github.com/users/janinko/gists{/gist_id}", - "starred_url": "https://api.github.com/users/janinko/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/janinko/subscriptions", - "organizations_url": "https://api.github.com/users/janinko/orgs", - "repos_url": "https://api.github.com/users/janinko/repos", - "events_url": "https://api.github.com/users/janinko/events{/privacy}", - "received_events_url": "https://api.github.com/users/janinko/received_events", - "type": "User", - "site_admin": false, - "contributions": 20 - }, - { - "login": "farmdawgnation", - "id": 620189, - "node_id": "MDQ6VXNlcjYyMDE4OQ==", - "avatar_url": "https://avatars2.githubusercontent.com/u/620189?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/farmdawgnation", - "html_url": "https://github.com/farmdawgnation", - "followers_url": "https://api.github.com/users/farmdawgnation/followers", - "following_url": "https://api.github.com/users/farmdawgnation/following{/other_user}", - "gists_url": "https://api.github.com/users/farmdawgnation/gists{/gist_id}", - "starred_url": "https://api.github.com/users/farmdawgnation/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/farmdawgnation/subscriptions", - "organizations_url": "https://api.github.com/users/farmdawgnation/orgs", - "repos_url": "https://api.github.com/users/farmdawgnation/repos", - "events_url": "https://api.github.com/users/farmdawgnation/events{/privacy}", - "received_events_url": "https://api.github.com/users/farmdawgnation/received_events", - "type": "User", - "site_admin": false, - "contributions": 16 - }, - { - "login": "johnou", - "id": 323497, - "node_id": "MDQ6VXNlcjMyMzQ5Nw==", - "avatar_url": "https://avatars2.githubusercontent.com/u/323497?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/johnou", - "html_url": "https://github.com/johnou", - "followers_url": "https://api.github.com/users/johnou/followers", - "following_url": "https://api.github.com/users/johnou/following{/other_user}", - "gists_url": "https://api.github.com/users/johnou/gists{/gist_id}", - "starred_url": "https://api.github.com/users/johnou/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/johnou/subscriptions", - "organizations_url": "https://api.github.com/users/johnou/orgs", - "repos_url": "https://api.github.com/users/johnou/repos", - "events_url": "https://api.github.com/users/johnou/events{/privacy}", - "received_events_url": "https://api.github.com/users/johnou/received_events", - "type": "User", - "site_admin": false, - "contributions": 13 - }, - { - "login": "mocleiri", - "id": 250942, - "node_id": "MDQ6VXNlcjI1MDk0Mg==", - "avatar_url": "https://avatars0.githubusercontent.com/u/250942?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/mocleiri", - "html_url": "https://github.com/mocleiri", - "followers_url": "https://api.github.com/users/mocleiri/followers", - "following_url": "https://api.github.com/users/mocleiri/following{/other_user}", - "gists_url": "https://api.github.com/users/mocleiri/gists{/gist_id}", - "starred_url": "https://api.github.com/users/mocleiri/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/mocleiri/subscriptions", - "organizations_url": "https://api.github.com/users/mocleiri/orgs", - "repos_url": "https://api.github.com/users/mocleiri/repos", - "events_url": "https://api.github.com/users/mocleiri/events{/privacy}", - "received_events_url": "https://api.github.com/users/mocleiri/received_events", - "type": "User", - "site_admin": false, - "contributions": 12 - }, - { - "login": "KostyaSha", - "id": 231611, - "node_id": "MDQ6VXNlcjIzMTYxMQ==", - "avatar_url": "https://avatars2.githubusercontent.com/u/231611?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/KostyaSha", - "html_url": "https://github.com/KostyaSha", - "followers_url": "https://api.github.com/users/KostyaSha/followers", - "following_url": "https://api.github.com/users/KostyaSha/following{/other_user}", - "gists_url": "https://api.github.com/users/KostyaSha/gists{/gist_id}", - "starred_url": "https://api.github.com/users/KostyaSha/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/KostyaSha/subscriptions", - "organizations_url": "https://api.github.com/users/KostyaSha/orgs", - "repos_url": "https://api.github.com/users/KostyaSha/repos", - "events_url": "https://api.github.com/users/KostyaSha/events{/privacy}", - "received_events_url": "https://api.github.com/users/KostyaSha/received_events", - "type": "User", - "site_admin": false, - "contributions": 12 - }, - { - "login": "jsoref", - "id": 2119212, - "node_id": "MDQ6VXNlcjIxMTkyMTI=", - "avatar_url": "https://avatars0.githubusercontent.com/u/2119212?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/jsoref", - "html_url": "https://github.com/jsoref", - "followers_url": "https://api.github.com/users/jsoref/followers", - "following_url": "https://api.github.com/users/jsoref/following{/other_user}", - "gists_url": "https://api.github.com/users/jsoref/gists{/gist_id}", - "starred_url": "https://api.github.com/users/jsoref/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/jsoref/subscriptions", - "organizations_url": "https://api.github.com/users/jsoref/orgs", - "repos_url": "https://api.github.com/users/jsoref/repos", - "events_url": "https://api.github.com/users/jsoref/events{/privacy}", - "received_events_url": "https://api.github.com/users/jsoref/received_events", - "type": "User", - "site_admin": false, - "contributions": 11 - }, - { - "login": "dependabot-preview[bot]", - "id": 27856297, - "node_id": "MDM6Qm90Mjc4NTYyOTc=", - "avatar_url": "https://avatars3.githubusercontent.com/in/2141?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/dependabot-preview%5Bbot%5D", - "html_url": "https://github.com/apps/dependabot-preview", - "followers_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/followers", - "following_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/following{/other_user}", - "gists_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/gists{/gist_id}", - "starred_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/subscriptions", - "organizations_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/orgs", - "repos_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/repos", - "events_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/events{/privacy}", - "received_events_url": "https://api.github.com/users/dependabot-preview%5Bbot%5D/received_events", - "type": "Bot", - "site_admin": false, - "contributions": 10 - }, - { - "login": "lucamilanesio", - "id": 182893, - "node_id": "MDQ6VXNlcjE4Mjg5Mw==", - "avatar_url": "https://avatars3.githubusercontent.com/u/182893?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/lucamilanesio", - "html_url": "https://github.com/lucamilanesio", - "followers_url": "https://api.github.com/users/lucamilanesio/followers", - "following_url": "https://api.github.com/users/lucamilanesio/following{/other_user}", - "gists_url": "https://api.github.com/users/lucamilanesio/gists{/gist_id}", - "starred_url": "https://api.github.com/users/lucamilanesio/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/lucamilanesio/subscriptions", - "organizations_url": "https://api.github.com/users/lucamilanesio/orgs", - "repos_url": "https://api.github.com/users/lucamilanesio/repos", - "events_url": "https://api.github.com/users/lucamilanesio/events{/privacy}", - "received_events_url": "https://api.github.com/users/lucamilanesio/received_events", - "type": "User", - "site_admin": false, - "contributions": 9 - }, - { - "login": "Shredder121", - "id": 4105066, - "node_id": "MDQ6VXNlcjQxMDUwNjY=", - "avatar_url": "https://avatars2.githubusercontent.com/u/4105066?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Shredder121", - "html_url": "https://github.com/Shredder121", - "followers_url": "https://api.github.com/users/Shredder121/followers", - "following_url": "https://api.github.com/users/Shredder121/following{/other_user}", - "gists_url": "https://api.github.com/users/Shredder121/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Shredder121/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Shredder121/subscriptions", - "organizations_url": "https://api.github.com/users/Shredder121/orgs", - "repos_url": "https://api.github.com/users/Shredder121/repos", - "events_url": "https://api.github.com/users/Shredder121/events{/privacy}", - "received_events_url": "https://api.github.com/users/Shredder121/received_events", - "type": "User", - "site_admin": false, - "contributions": 9 - }, - { - "login": "rtyley", - "id": 52038, - "node_id": "MDQ6VXNlcjUyMDM4", - "avatar_url": "https://avatars3.githubusercontent.com/u/52038?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/rtyley", - "html_url": "https://github.com/rtyley", - "followers_url": "https://api.github.com/users/rtyley/followers", - "following_url": "https://api.github.com/users/rtyley/following{/other_user}", - "gists_url": "https://api.github.com/users/rtyley/gists{/gist_id}", - "starred_url": "https://api.github.com/users/rtyley/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/rtyley/subscriptions", - "organizations_url": "https://api.github.com/users/rtyley/orgs", - "repos_url": "https://api.github.com/users/rtyley/repos", - "events_url": "https://api.github.com/users/rtyley/events{/privacy}", - "received_events_url": "https://api.github.com/users/rtyley/received_events", - "type": "User", - "site_admin": false, - "contributions": 9 - }, - { - "login": "jglick", - "id": 154109, - "node_id": "MDQ6VXNlcjE1NDEwOQ==", - "avatar_url": "https://avatars1.githubusercontent.com/u/154109?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/jglick", - "html_url": "https://github.com/jglick", - "followers_url": "https://api.github.com/users/jglick/followers", - "following_url": "https://api.github.com/users/jglick/following{/other_user}", - "gists_url": "https://api.github.com/users/jglick/gists{/gist_id}", - "starred_url": "https://api.github.com/users/jglick/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/jglick/subscriptions", - "organizations_url": "https://api.github.com/users/jglick/orgs", - "repos_url": "https://api.github.com/users/jglick/repos", - "events_url": "https://api.github.com/users/jglick/events{/privacy}", - "received_events_url": "https://api.github.com/users/jglick/received_events", - "type": "User", - "site_admin": false, - "contributions": 8 - }, - { - "login": "oleg-nenashev", - "id": 3000480, - "node_id": "MDQ6VXNlcjMwMDA0ODA=", - "avatar_url": "https://avatars0.githubusercontent.com/u/3000480?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/oleg-nenashev", - "html_url": "https://github.com/oleg-nenashev", - "followers_url": "https://api.github.com/users/oleg-nenashev/followers", - "following_url": "https://api.github.com/users/oleg-nenashev/following{/other_user}", - "gists_url": "https://api.github.com/users/oleg-nenashev/gists{/gist_id}", - "starred_url": "https://api.github.com/users/oleg-nenashev/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/oleg-nenashev/subscriptions", - "organizations_url": "https://api.github.com/users/oleg-nenashev/orgs", - "repos_url": "https://api.github.com/users/oleg-nenashev/repos", - "events_url": "https://api.github.com/users/oleg-nenashev/events{/privacy}", - "received_events_url": "https://api.github.com/users/oleg-nenashev/received_events", - "type": "User", - "site_admin": false, - "contributions": 8 - }, - { - "login": "recena", - "id": 1021745, - "node_id": "MDQ6VXNlcjEwMjE3NDU=", - "avatar_url": "https://avatars3.githubusercontent.com/u/1021745?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/recena", - "html_url": "https://github.com/recena", - "followers_url": "https://api.github.com/users/recena/followers", - "following_url": "https://api.github.com/users/recena/following{/other_user}", - "gists_url": "https://api.github.com/users/recena/gists{/gist_id}", - "starred_url": "https://api.github.com/users/recena/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/recena/subscriptions", - "organizations_url": "https://api.github.com/users/recena/orgs", - "repos_url": "https://api.github.com/users/recena/repos", - "events_url": "https://api.github.com/users/recena/events{/privacy}", - "received_events_url": "https://api.github.com/users/recena/received_events", - "type": "User", - "site_admin": false, - "contributions": 7 - }, - { - "login": "vr100", - "id": 6443683, - "node_id": "MDQ6VXNlcjY0NDM2ODM=", - "avatar_url": "https://avatars2.githubusercontent.com/u/6443683?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/vr100", - "html_url": "https://github.com/vr100", - "followers_url": "https://api.github.com/users/vr100/followers", - "following_url": "https://api.github.com/users/vr100/following{/other_user}", - "gists_url": "https://api.github.com/users/vr100/gists{/gist_id}", - "starred_url": "https://api.github.com/users/vr100/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/vr100/subscriptions", - "organizations_url": "https://api.github.com/users/vr100/orgs", - "repos_url": "https://api.github.com/users/vr100/repos", - "events_url": "https://api.github.com/users/vr100/events{/privacy}", - "received_events_url": "https://api.github.com/users/vr100/received_events", - "type": "User", - "site_admin": false, - "contributions": 6 - }, - { - "login": "jgangemi", - "id": 1831839, - "node_id": "MDQ6VXNlcjE4MzE4Mzk=", - "avatar_url": "https://avatars0.githubusercontent.com/u/1831839?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/jgangemi", - "html_url": "https://github.com/jgangemi", - "followers_url": "https://api.github.com/users/jgangemi/followers", - "following_url": "https://api.github.com/users/jgangemi/following{/other_user}", - "gists_url": "https://api.github.com/users/jgangemi/gists{/gist_id}", - "starred_url": "https://api.github.com/users/jgangemi/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/jgangemi/subscriptions", - "organizations_url": "https://api.github.com/users/jgangemi/orgs", - "repos_url": "https://api.github.com/users/jgangemi/repos", - "events_url": "https://api.github.com/users/jgangemi/events{/privacy}", - "received_events_url": "https://api.github.com/users/jgangemi/received_events", - "type": "User", - "site_admin": false, - "contributions": 5 - }, - { - "login": "sns-seb", - "id": 11717580, - "node_id": "MDQ6VXNlcjExNzE3NTgw", - "avatar_url": "https://avatars2.githubusercontent.com/u/11717580?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/sns-seb", - "html_url": "https://github.com/sns-seb", - "followers_url": "https://api.github.com/users/sns-seb/followers", - "following_url": "https://api.github.com/users/sns-seb/following{/other_user}", - "gists_url": "https://api.github.com/users/sns-seb/gists{/gist_id}", - "starred_url": "https://api.github.com/users/sns-seb/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/sns-seb/subscriptions", - "organizations_url": "https://api.github.com/users/sns-seb/orgs", - "repos_url": "https://api.github.com/users/sns-seb/repos", - "events_url": "https://api.github.com/users/sns-seb/events{/privacy}", - "received_events_url": "https://api.github.com/users/sns-seb/received_events", - "type": "User", - "site_admin": false, - "contributions": 5 - }, - { - "login": "marc-guenther", - "id": 393230, - "node_id": "MDQ6VXNlcjM5MzIzMA==", - "avatar_url": "https://avatars3.githubusercontent.com/u/393230?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/marc-guenther", - "html_url": "https://github.com/marc-guenther", - "followers_url": "https://api.github.com/users/marc-guenther/followers", - "following_url": "https://api.github.com/users/marc-guenther/following{/other_user}", - "gists_url": "https://api.github.com/users/marc-guenther/gists{/gist_id}", - "starred_url": "https://api.github.com/users/marc-guenther/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/marc-guenther/subscriptions", - "organizations_url": "https://api.github.com/users/marc-guenther/orgs", - "repos_url": "https://api.github.com/users/marc-guenther/repos", - "events_url": "https://api.github.com/users/marc-guenther/events{/privacy}", - "received_events_url": "https://api.github.com/users/marc-guenther/received_events", - "type": "User", - "site_admin": false, - "contributions": 4 - }, - { - "login": "mmitche", - "id": 8725170, - "node_id": "MDQ6VXNlcjg3MjUxNzA=", - "avatar_url": "https://avatars1.githubusercontent.com/u/8725170?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/mmitche", - "html_url": "https://github.com/mmitche", - "followers_url": "https://api.github.com/users/mmitche/followers", - "following_url": "https://api.github.com/users/mmitche/following{/other_user}", - "gists_url": "https://api.github.com/users/mmitche/gists{/gist_id}", - "starred_url": "https://api.github.com/users/mmitche/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/mmitche/subscriptions", - "organizations_url": "https://api.github.com/users/mmitche/orgs", - "repos_url": "https://api.github.com/users/mmitche/repos", - "events_url": "https://api.github.com/users/mmitche/events{/privacy}", - "received_events_url": "https://api.github.com/users/mmitche/received_events", - "type": "User", - "site_admin": false, - "contributions": 4 - }, - { - "login": "lanwen", - "id": 1964214, - "node_id": "MDQ6VXNlcjE5NjQyMTQ=", - "avatar_url": "https://avatars1.githubusercontent.com/u/1964214?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/lanwen", - "html_url": "https://github.com/lanwen", - "followers_url": "https://api.github.com/users/lanwen/followers", - "following_url": "https://api.github.com/users/lanwen/following{/other_user}", - "gists_url": "https://api.github.com/users/lanwen/gists{/gist_id}", - "starred_url": "https://api.github.com/users/lanwen/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/lanwen/subscriptions", - "organizations_url": "https://api.github.com/users/lanwen/orgs", - "repos_url": "https://api.github.com/users/lanwen/repos", - "events_url": "https://api.github.com/users/lanwen/events{/privacy}", - "received_events_url": "https://api.github.com/users/lanwen/received_events", - "type": "User", - "site_admin": false, - "contributions": 4 - }, - { - "login": "suryagaddipati", - "id": 64078, - "node_id": "MDQ6VXNlcjY0MDc4", - "avatar_url": "https://avatars3.githubusercontent.com/u/64078?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/suryagaddipati", - "html_url": "https://github.com/suryagaddipati", - "followers_url": "https://api.github.com/users/suryagaddipati/followers", - "following_url": "https://api.github.com/users/suryagaddipati/following{/other_user}", - "gists_url": "https://api.github.com/users/suryagaddipati/gists{/gist_id}", - "starred_url": "https://api.github.com/users/suryagaddipati/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/suryagaddipati/subscriptions", - "organizations_url": "https://api.github.com/users/suryagaddipati/orgs", - "repos_url": "https://api.github.com/users/suryagaddipati/repos", - "events_url": "https://api.github.com/users/suryagaddipati/events{/privacy}", - "received_events_url": "https://api.github.com/users/suryagaddipati/received_events", - "type": "User", - "site_admin": false, - "contributions": 4 - }, - { - "login": "kamontat", - "id": 14089557, - "node_id": "MDQ6VXNlcjE0MDg5NTU3", - "avatar_url": "https://avatars2.githubusercontent.com/u/14089557?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/kamontat", - "html_url": "https://github.com/kamontat", - "followers_url": "https://api.github.com/users/kamontat/followers", - "following_url": "https://api.github.com/users/kamontat/following{/other_user}", - "gists_url": "https://api.github.com/users/kamontat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/kamontat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/kamontat/subscriptions", - "organizations_url": "https://api.github.com/users/kamontat/orgs", - "repos_url": "https://api.github.com/users/kamontat/repos", - "events_url": "https://api.github.com/users/kamontat/events{/privacy}", - "received_events_url": "https://api.github.com/users/kamontat/received_events", - "type": "User", - "site_admin": false, - "contributions": 4 - }, - { - "login": "watsonian", - "id": 244, - "node_id": "MDQ6VXNlcjI0NA==", - "avatar_url": "https://avatars3.githubusercontent.com/u/244?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/watsonian", - "html_url": "https://github.com/watsonian", - "followers_url": "https://api.github.com/users/watsonian/followers", - "following_url": "https://api.github.com/users/watsonian/following{/other_user}", - "gists_url": "https://api.github.com/users/watsonian/gists{/gist_id}", - "starred_url": "https://api.github.com/users/watsonian/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/watsonian/subscriptions", - "organizations_url": "https://api.github.com/users/watsonian/orgs", - "repos_url": "https://api.github.com/users/watsonian/repos", - "events_url": "https://api.github.com/users/watsonian/events{/privacy}", - "received_events_url": "https://api.github.com/users/watsonian/received_events", - "type": "User", - "site_admin": false, - "contributions": 4 - }, - { - "login": "arngrimur-seal", - "id": 36759268, - "node_id": "MDQ6VXNlcjM2NzU5MjY4", - "avatar_url": "https://avatars3.githubusercontent.com/u/36759268?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/arngrimur-seal", - "html_url": "https://github.com/arngrimur-seal", - "followers_url": "https://api.github.com/users/arngrimur-seal/followers", - "following_url": "https://api.github.com/users/arngrimur-seal/following{/other_user}", - "gists_url": "https://api.github.com/users/arngrimur-seal/gists{/gist_id}", - "starred_url": "https://api.github.com/users/arngrimur-seal/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/arngrimur-seal/subscriptions", - "organizations_url": "https://api.github.com/users/arngrimur-seal/orgs", - "repos_url": "https://api.github.com/users/arngrimur-seal/repos", - "events_url": "https://api.github.com/users/arngrimur-seal/events{/privacy}", - "received_events_url": "https://api.github.com/users/arngrimur-seal/received_events", - "type": "User", - "site_admin": false, - "contributions": 3 - }, - { - "login": "ashwanthkumar", - "id": 600279, - "node_id": "MDQ6VXNlcjYwMDI3OQ==", - "avatar_url": "https://avatars0.githubusercontent.com/u/600279?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/ashwanthkumar", - "html_url": "https://github.com/ashwanthkumar", - "followers_url": "https://api.github.com/users/ashwanthkumar/followers", - "following_url": "https://api.github.com/users/ashwanthkumar/following{/other_user}", - "gists_url": "https://api.github.com/users/ashwanthkumar/gists{/gist_id}", - "starred_url": "https://api.github.com/users/ashwanthkumar/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/ashwanthkumar/subscriptions", - "organizations_url": "https://api.github.com/users/ashwanthkumar/orgs", - "repos_url": "https://api.github.com/users/ashwanthkumar/repos", - "events_url": "https://api.github.com/users/ashwanthkumar/events{/privacy}", - "received_events_url": "https://api.github.com/users/ashwanthkumar/received_events", - "type": "User", - "site_admin": false, - "contributions": 3 - }, - { - "login": "cyrille-leclerc", - "id": 459691, - "node_id": "MDQ6VXNlcjQ1OTY5MQ==", - "avatar_url": "https://avatars3.githubusercontent.com/u/459691?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/cyrille-leclerc", - "html_url": "https://github.com/cyrille-leclerc", - "followers_url": "https://api.github.com/users/cyrille-leclerc/followers", - "following_url": "https://api.github.com/users/cyrille-leclerc/following{/other_user}", - "gists_url": "https://api.github.com/users/cyrille-leclerc/gists{/gist_id}", - "starred_url": "https://api.github.com/users/cyrille-leclerc/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/cyrille-leclerc/subscriptions", - "organizations_url": "https://api.github.com/users/cyrille-leclerc/orgs", - "repos_url": "https://api.github.com/users/cyrille-leclerc/repos", - "events_url": "https://api.github.com/users/cyrille-leclerc/events{/privacy}", - "received_events_url": "https://api.github.com/users/cyrille-leclerc/received_events", - "type": "User", - "site_admin": false, - "contributions": 3 - }, - { - "login": "daniel-beck", - "id": 1831569, - "node_id": "MDQ6VXNlcjE4MzE1Njk=", - "avatar_url": "https://avatars3.githubusercontent.com/u/1831569?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/daniel-beck", - "html_url": "https://github.com/daniel-beck", - "followers_url": "https://api.github.com/users/daniel-beck/followers", - "following_url": "https://api.github.com/users/daniel-beck/following{/other_user}", - "gists_url": "https://api.github.com/users/daniel-beck/gists{/gist_id}", - "starred_url": "https://api.github.com/users/daniel-beck/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/daniel-beck/subscriptions", - "organizations_url": "https://api.github.com/users/daniel-beck/orgs", - "repos_url": "https://api.github.com/users/daniel-beck/repos", - "events_url": "https://api.github.com/users/daniel-beck/events{/privacy}", - "received_events_url": "https://api.github.com/users/daniel-beck/received_events", - "type": "User", - "site_admin": false, - "contributions": 3 - }, - { - "login": "dlovera", - "id": 4728774, - "node_id": "MDQ6VXNlcjQ3Mjg3NzQ=", - "avatar_url": "https://avatars1.githubusercontent.com/u/4728774?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/dlovera", - "html_url": "https://github.com/dlovera", - "followers_url": "https://api.github.com/users/dlovera/followers", - "following_url": "https://api.github.com/users/dlovera/following{/other_user}", - "gists_url": "https://api.github.com/users/dlovera/gists{/gist_id}", - "starred_url": "https://api.github.com/users/dlovera/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/dlovera/subscriptions", - "organizations_url": "https://api.github.com/users/dlovera/orgs", - "repos_url": "https://api.github.com/users/dlovera/repos", - "events_url": "https://api.github.com/users/dlovera/events{/privacy}", - "received_events_url": "https://api.github.com/users/dlovera/received_events", - "type": "User", - "site_admin": false, - "contributions": 3 - } -] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/1-user.json deleted file mode 100644 index 38fbee0bea..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "5705a11e-1421-4985-8e1f-b1e25b4ef547", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Thu, 03 Oct 2019 18:56:02 GMT", - "Content-Type": "application/json; charset=utf-8", - "Server": "GitHub.com", - "Status": "200 OK", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4924", - "X-RateLimit-Reset": "1570132527", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": [ - "Accept, Authorization, Cookie, X-GitHub-OTP", - "Accept-Encoding" - ], - "ETag": "W/\"cf6199fecf47b59c42190e1e11147ee2\"", - "Last-Modified": "Tue, 24 Sep 2019 19:32:29 GMT", - "X-OAuth-Scopes": "admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "unknown, github.v3", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "X-GitHub-Request-Id": "F355:2CE7:106E772:13682E3:5D964442" - } - }, - "uuid": "5705a11e-1421-4985-8e1f-b1e25b4ef547", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/10-users_kohsuke.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/10-users_kohsuke.json deleted file mode 100644 index 27677cb055..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/10-users_kohsuke.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "8e9d982b-ca60-4410-a263-d2c49834c0df", - "name": "users_kohsuke", - "request": { - "url": "/users/kohsuke", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "10-users_kohsuke.json", - "headers": { - "Server": "GitHub.com", - "Date": "Mon, 18 Apr 2022 19:55:03 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": [ - "Accept, Authorization, Cookie, X-GitHub-OTP", - "Accept-Encoding, Accept, X-Requested-With" - ], - "ETag": "W/\"4ca7cbddf39c9811d84469a3e5d3d4e4e577b18bc9798e19eac336ba991a7300\"", - "Last-Modified": "Sun, 10 Apr 2022 22:58:15 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, gist, notifications, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4964", - "X-RateLimit-Reset": "1650312871", - "X-RateLimit-Used": "36", - "X-RateLimit-Resource": "core", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "X-GitHub-Request-Id": "C7B2:C448:2A6BF2A:2B14CE1:625DC217" - } - }, - "uuid": "8e9d982b-ca60-4410-a263-d2c49834c0df", - "persistent": true, - "insertionIndex": 10 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/2-orgs_hub4j.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/2-orgs_hub4j.json deleted file mode 100644 index 44180982f4..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/2-orgs_hub4j.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "7c4b2a82-e18f-45a2-a6b5-4baaea191b89", - "name": "orgs_hub4j", - "request": { - "url": "/orgs/hub4j", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-orgs_hub4j.json", - "headers": { - "Date": "Thu, 03 Oct 2019 18:56:03 GMT", - "Content-Type": "application/json; charset=utf-8", - "Server": "GitHub.com", - "Status": "200 OK", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4922", - "X-RateLimit-Reset": "1570132527", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": [ - "Accept, Authorization, Cookie, X-GitHub-OTP", - "Accept-Encoding" - ], - "ETag": "W/\"62b7633c1dd73301f853bcc0da2d8504\"", - "Last-Modified": "Wed, 04 Sep 2019 18:12:34 GMT", - "X-OAuth-Scopes": "admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion", - "X-Accepted-OAuth-Scopes": "admin:org, read:org, repo, user, write:org", - "X-GitHub-Media-Type": "unknown, github.v3", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "X-GitHub-Request-Id": "F355:2CE7:106E7C3:13682F9:5D964442" - } - }, - "uuid": "7c4b2a82-e18f-45a2-a6b5-4baaea191b89", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/3-r_h_github-api.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/3-r_h_github-api.json deleted file mode 100644 index 94e1d632c6..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/3-r_h_github-api.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "d87d9579-8da1-4f01-a6e6-6f91e04cc8a7", - "name": "repos_hub4j_github-api", - "request": { - "url": "/repos/hub4j/github-api", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "3-r_h_github-api.json", - "headers": { - "Date": "Thu, 03 Oct 2019 18:56:03 GMT", - "Content-Type": "application/json; charset=utf-8", - "Server": "GitHub.com", - "Status": "200 OK", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4921", - "X-RateLimit-Reset": "1570132527", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": [ - "Accept, Authorization, Cookie, X-GitHub-OTP", - "Accept-Encoding" - ], - "ETag": "W/\"ee2a44ea003736b3fc98deff8fb5ff11\"", - "Last-Modified": "Thu, 03 Oct 2019 09:41:10 GMT", - "X-OAuth-Scopes": "admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion", - "X-Accepted-OAuth-Scopes": "repo", - "X-GitHub-Media-Type": "unknown, github.v3", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "X-GitHub-Request-Id": "F355:2CE7:106E7D7:1368356:5D964443" - } - }, - "uuid": "d87d9579-8da1-4f01-a6e6-6f91e04cc8a7", - "persistent": true, - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/4-r_h_g_contributors.json b/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/4-r_h_g_contributors.json deleted file mode 100644 index c0009b30b6..0000000000 --- a/src/test/resources/org/kohsuke/github/GHRepositoryTest/wiremock/listContributorsAnon/mappings/4-r_h_g_contributors.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "id": "cd622100-1a8e-4b33-9716-dbaf0b55c2aa", - "name": "repos_hub4j_github-api_contributors", - "request": { - "url": "/repos/hub4j/github-api/contributors?anon=true", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "4-r_h_g_contributors.json", - "headers": { - "Date": "Thu, 03 Oct 2019 18:56:03 GMT", - "Content-Type": "application/json; charset=utf-8", - "Server": "GitHub.com", - "Status": "200 OK", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4920", - "X-RateLimit-Reset": "1570132527", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": [ - "Accept, Authorization, Cookie, X-GitHub-OTP", - "Accept-Encoding" - ], - "ETag": "W/\"a1b7dbc652ab098b5033f9fa5b3bfc62\"", - "Last-Modified": "Thu, 03 Oct 2019 09:41:10 GMT", - "X-OAuth-Scopes": "admin:org, admin:org_hook, admin:public_key, admin:repo_hook, delete_repo, gist, notifications, repo, user, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "unknown, github.v3", - "Link": "; rel=\"next\", ; rel=\"last\"", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "1; mode=block", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "X-GitHub-Request-Id": "F355:2CE7:106E7F3:1368377:5D964443" - } - }, - "uuid": "cd622100-1a8e-4b33-9716-dbaf0b55c2aa", - "persistent": true, - "insertionIndex": 4 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GHWorkflowRunTest/wiremock/testManualRunAndBasicInformation/__files/6-r_h_g_actions_runs.json b/src/test/resources/org/kohsuke/github/GHWorkflowRunTest/wiremock/testManualRunAndBasicInformation/__files/6-r_h_g_actions_runs.json index 00b4c827d6..09bc9af45f 100644 --- a/src/test/resources/org/kohsuke/github/GHWorkflowRunTest/wiremock/testManualRunAndBasicInformation/__files/6-r_h_g_actions_runs.json +++ b/src/test/resources/org/kohsuke/github/GHWorkflowRunTest/wiremock/testManualRunAndBasicInformation/__files/6-r_h_g_actions_runs.json @@ -26,26 +26,6 @@ "cancel_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/actions/runs/686034992/cancel", "rerun_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/actions/runs/686034992/rerun", "workflow_url": "https://api.github.com/repos/hub4j-test-org/GHWorkflowRunTest/actions/workflows/6820790", - "triggering_actor": { - "login": "octocat", - "id": 1, - "node_id": "MDQ6VXNlcjE=", - "avatar_url": "https://github.com/images/error/octocat_happy.gif", - "gravatar_id": "", - "url": "https://api.github.com/users/octocat", - "html_url": "https://github.com/octocat", - "followers_url": "https://api.github.com/users/octocat/followers", - "following_url": "https://api.github.com/users/octocat/following{/other_user}", - "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", - "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", - "organizations_url": "https://api.github.com/users/octocat/orgs", - "repos_url": "https://api.github.com/users/octocat/repos", - "events_url": "https://api.github.com/users/octocat/events{/privacy}", - "received_events_url": "https://api.github.com/users/octocat/received_events", - "type": "User", - "site_admin": false - }, "head_commit": { "id": "f6a5c19a67797d64426203b8a7a05a0fd74e5037", "tree_id": "666bb9f951306171acb21632eca28a386cb35f73", diff --git a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/getMeta/__files/1-meta.json b/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/getMeta/__files/1-meta.json index d66ad1746e..2baa8baf32 100644 --- a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/getMeta/__files/1-meta.json +++ b/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/getMeta/__files/1-meta.json @@ -1,16 +1,5 @@ { "verifiable_password_authentication": true, - "ssh_key_fingerprints": { - "SHA256_RSA": 1234567890, - "SHA256_DSA": 1234567890, - "SHA256_ECDSA": 1234567890, - "SHA256_ED25519": 1234567890 - }, - "ssh_keys": [ - "ssh-ed25519 ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "ecdsa-sha2-nistp256 ABCDEFGHIJKLMNOPQRSTUVWXYZ", - "ssh-rsa ABCDEFGHIJKLMNOPQRSTUVWXYZ" - ], "hooks": [ "192.30.252.0/22", "185.199.108.0/22", diff --git a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/1-user.json b/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/1-user.json deleted file mode 100644 index bc76bc73d6..0000000000 --- a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "anujhydrabadi", - "id": 129152617, - "node_id": "U_kgDOB7K2aQ", - "avatar_url": "https://avatars.githubusercontent.com/u/129152617?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/anujhydrabadi", - "html_url": "https://github.com/anujhydrabadi", - "followers_url": "https://api.github.com/users/anujhydrabadi/followers", - "following_url": "https://api.github.com/users/anujhydrabadi/following{/other_user}", - "gists_url": "https://api.github.com/users/anujhydrabadi/gists{/gist_id}", - "starred_url": "https://api.github.com/users/anujhydrabadi/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/anujhydrabadi/subscriptions", - "organizations_url": "https://api.github.com/users/anujhydrabadi/orgs", - "repos_url": "https://api.github.com/users/anujhydrabadi/repos", - "events_url": "https://api.github.com/users/anujhydrabadi/events{/privacy}", - "received_events_url": "https://api.github.com/users/anujhydrabadi/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Anuj Hydrabadi", - "company": "@Facets-cloud", - "blog": "", - "location": null, - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 6, - "public_gists": 1, - "followers": 0, - "following": 0, - "created_at": "2023-03-28T07:02:48Z", - "updated_at": "2025-01-31T11:08:30Z", - "private_gists": 0, - "total_private_repos": 28, - "owned_private_repos": 28, - "disk_usage": 1269, - "collaborators": 2, - "two_factor_authentication": true, - "plan": { - "name": "free", - "space": 976562499, - "collaborators": 0, - "private_repos": 10000 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/2-organizations.json b/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/2-organizations.json deleted file mode 100644 index 3c98fb9cef..0000000000 --- a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/2-organizations.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "login": "errfree", - "id": 44, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjQ0", - "url": "https://api.github.com/orgs/errfree", - "repos_url": "https://api.github.com/orgs/errfree/repos", - "events_url": "https://api.github.com/orgs/errfree/events", - "hooks_url": "https://api.github.com/orgs/errfree/hooks", - "issues_url": "https://api.github.com/orgs/errfree/issues", - "members_url": "https://api.github.com/orgs/errfree/members{/member}", - "public_members_url": "https://api.github.com/orgs/errfree/public_members{/member}", - "avatar_url": "https://avatars.githubusercontent.com/u/44?v=4", - "description": null - } -] \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/3-orgs_errfree.json b/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/3-orgs_errfree.json deleted file mode 100644 index 1f6b52cf4a..0000000000 --- a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/__files/3-orgs_errfree.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "login": "errfree", - "id": 44, - "node_id": "MDEyOk9yZ2FuaXphdGlvbjQ0", - "url": "https://api.github.com/orgs/errfree", - "repos_url": "https://api.github.com/orgs/errfree/repos", - "events_url": "https://api.github.com/orgs/errfree/events", - "hooks_url": "https://api.github.com/orgs/errfree/hooks", - "issues_url": "https://api.github.com/orgs/errfree/issues", - "members_url": "https://api.github.com/orgs/errfree/members{/member}", - "public_members_url": "https://api.github.com/orgs/errfree/public_members{/member}", - "avatar_url": "https://avatars.githubusercontent.com/u/44?v=4", - "description": null, - "is_verified": false, - "has_organization_projects": true, - "has_repository_projects": true, - "public_repos": 2, - "public_gists": 0, - "followers": 14, - "following": 0, - "html_url": "https://github.com/errfree", - "created_at": "2008-01-24T02:08:37Z", - "updated_at": "2020-05-13T06:35:19Z", - "archived_at": null, - "type": "Organization" -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/1-user.json b/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/1-user.json deleted file mode 100644 index e1a7e928a1..0000000000 --- a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/1-user.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "cd7530db-bd05-4525-9136-0bf80e609c23", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Sun, 16 Feb 2025 09:01:24 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"2288274ffc402f5864177c99f29e71d41d774342ce2b6fc9d2b12db0df22c6ef\"", - "Last-Modified": "Fri, 31 Jan 2025 11:08:30 GMT", - "X-OAuth-Scopes": "admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, notifications, project, repo, user, workflow, write:discussion, write:packages", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4962", - "X-RateLimit-Reset": "1739697044", - "X-RateLimit-Used": "38", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "415A:2933E2:783482:ABFF69:67B1A964" - } - }, - "uuid": "cd7530db-bd05-4525-9136-0bf80e609c23", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/2-organizations.json b/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/2-organizations.json deleted file mode 100644 index e53cbf1764..0000000000 --- a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/2-organizations.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "87f5d76b-1169-4caf-ab76-04ac6b1e78b9", - "name": "organizations", - "request": { - "url": "/organizations?per_page=1", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "2-organizations.json", - "headers": { - "Date": "Sun, 16 Feb 2025 09:01:25 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"575d7c16fc728d88180cb71aecfb2c215cdf28f0259a6eac1d93c607816f3722\"", - "X-OAuth-Scopes": "admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, notifications, project, repo, user, workflow, write:discussion, write:packages", - "X-Accepted-OAuth-Scopes": "", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4960", - "X-RateLimit-Reset": "1739697044", - "X-RateLimit-Used": "40", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "58BE:2FA953:5F36F5:9301D2:67B1A965", - "Link": "; rel=\"next\", ; rel=\"first\"" - } - }, - "uuid": "87f5d76b-1169-4caf-ab76-04ac6b1e78b9", - "persistent": true, - "insertionIndex": 2 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/3-orgs_errfree.json b/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/3-orgs_errfree.json deleted file mode 100644 index 13a81e17a3..0000000000 --- a/src/test/resources/org/kohsuke/github/GitHubTest/wiremock/listOrganizationsFetchesType/mappings/3-orgs_errfree.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "id": "950bf65f-6dda-43d1-9ded-907e269024df", - "name": "orgs_errfree", - "request": { - "url": "/orgs/errfree", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "3-orgs_errfree.json", - "headers": { - "Date": "Sun, 16 Feb 2025 09:01:25 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"fdf38082b2dec2c4293a820e9f615c582c00ca7ab2365a5db1a7f7a3a1905dbd\"", - "Last-Modified": "Wed, 13 May 2020 06:35:19 GMT", - "X-OAuth-Scopes": "admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, notifications, project, repo, user, workflow, write:discussion, write:packages", - "X-Accepted-OAuth-Scopes": "admin:org, read:org, repo, user, write:org", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4959", - "X-RateLimit-Reset": "1739697044", - "X-RateLimit-Used": "41", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "1EF0:22ABA6:638768:974F6C:67B1A965" - } - }, - "uuid": "950bf65f-6dda-43d1-9ded-907e269024df", - "persistent": true, - "insertionIndex": 3 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/user_whenProxying_AuthCorrectlyConfigured/__files/1-user.json b/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/user_whenProxying_AuthCorrectlyConfigured/__files/1-user.json deleted file mode 100644 index 56ff784983..0000000000 --- a/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/user_whenProxying_AuthCorrectlyConfigured/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": null, - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 7, - "public_gists": 0, - "followers": 3, - "following": 8, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-11-27T04:01:41Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/user_whenProxying_AuthCorrectlyConfigured/mappings/1-user.json b/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/user_whenProxying_AuthCorrectlyConfigured/mappings/1-user.json deleted file mode 100644 index 97d97463cf..0000000000 --- a/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/user_whenProxying_AuthCorrectlyConfigured/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "64916a9b-5eda-42af-9c98-48ae56c4d534", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Thu, 28 Nov 2024 03:26:34 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"649a1838c989cc406542c8419b31064e1c7a6202454895df13e7b35e43b8653b\"", - "Last-Modified": "Wed, 27 Nov 2024 04:01:41 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4881", - "X-RateLimit-Reset": "1732767344", - "X-RateLimit-Used": "119", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AA1E:348A76:BD20B0:DB5BDF:6747E2EA" - } - }, - "uuid": "64916a9b-5eda-42af-9c98-48ae56c4d534", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/whenSnapshot_EnsureProxy/__files/1-user.json b/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/whenSnapshot_EnsureProxy/__files/1-user.json deleted file mode 100644 index 56ff784983..0000000000 --- a/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/whenSnapshot_EnsureProxy/__files/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "login": "Alaurant", - "id": 41817560, - "node_id": "MDQ6VXNlcjQxODE3NTYw", - "avatar_url": "https://avatars.githubusercontent.com/u/41817560?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/Alaurant", - "html_url": "https://github.com/Alaurant", - "followers_url": "https://api.github.com/users/Alaurant/followers", - "following_url": "https://api.github.com/users/Alaurant/following{/other_user}", - "gists_url": "https://api.github.com/users/Alaurant/gists{/gist_id}", - "starred_url": "https://api.github.com/users/Alaurant/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/Alaurant/subscriptions", - "organizations_url": "https://api.github.com/users/Alaurant/orgs", - "repos_url": "https://api.github.com/users/Alaurant/repos", - "events_url": "https://api.github.com/users/Alaurant/events{/privacy}", - "received_events_url": "https://api.github.com/users/Alaurant/received_events", - "type": "User", - "user_view_type": "private", - "site_admin": false, - "name": "Danyang Zhao", - "company": null, - "blog": "", - "location": null, - "email": null, - "hireable": null, - "bio": null, - "twitter_username": null, - "notification_email": null, - "public_repos": 7, - "public_gists": 0, - "followers": 3, - "following": 8, - "created_at": "2018-07-28T07:03:48Z", - "updated_at": "2024-11-27T04:01:41Z", - "private_gists": 0, - "total_private_repos": 2, - "owned_private_repos": 2, - "disk_usage": 7314, - "collaborators": 0, - "two_factor_authentication": false, - "plan": { - "name": "pro", - "space": 976562499, - "collaborators": 0, - "private_repos": 9999 - } -} \ No newline at end of file diff --git a/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/whenSnapshot_EnsureProxy/mappings/1-user.json b/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/whenSnapshot_EnsureProxy/mappings/1-user.json deleted file mode 100644 index 0d35435e64..0000000000 --- a/src/test/resources/org/kohsuke/github/WireMockStatusReporterTest/wiremock/whenSnapshot_EnsureProxy/mappings/1-user.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "id": "7de2b730-9b8e-4691-a676-4458c8cfd026", - "name": "user", - "request": { - "url": "/user", - "method": "GET", - "headers": { - "Accept": { - "equalTo": "application/vnd.github+json" - } - } - }, - "response": { - "status": 200, - "bodyFileName": "1-user.json", - "headers": { - "Date": "Thu, 28 Nov 2024 03:26:33 GMT", - "Content-Type": "application/json; charset=utf-8", - "Cache-Control": "private, max-age=60, s-maxage=60", - "Vary": "Accept, Authorization, Cookie, X-GitHub-OTP,Accept-Encoding, Accept, X-Requested-With", - "ETag": "W/\"649a1838c989cc406542c8419b31064e1c7a6202454895df13e7b35e43b8653b\"", - "Last-Modified": "Wed, 27 Nov 2024 04:01:41 GMT", - "X-OAuth-Scopes": "admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, audit_log, codespace, delete:packages, delete_repo, gist, project, read:packages, repo, user, workflow, write:discussion", - "X-Accepted-OAuth-Scopes": "", - "github-authentication-token-expiration": "2025-02-25 04:28:56 UTC", - "X-GitHub-Media-Type": "github.v3; format=json", - "x-github-api-version-selected": "2022-11-28", - "X-RateLimit-Limit": "5000", - "X-RateLimit-Remaining": "4883", - "X-RateLimit-Reset": "1732767344", - "X-RateLimit-Used": "117", - "X-RateLimit-Resource": "core", - "Access-Control-Expose-Headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", - "Access-Control-Allow-Origin": "*", - "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", - "X-Frame-Options": "deny", - "X-Content-Type-Options": "nosniff", - "X-XSS-Protection": "0", - "Referrer-Policy": "origin-when-cross-origin, strict-origin-when-cross-origin", - "Content-Security-Policy": "default-src 'none'", - "Server": "github.com", - "X-GitHub-Request-Id": "AA13:3A04E5:529DA2:61BA25:6747E2E9" - } - }, - "uuid": "7de2b730-9b8e-4691-a676-4458c8cfd026", - "persistent": true, - "insertionIndex": 1 -} \ No newline at end of file diff --git a/src/test/resources/reflection-and-serialization-test-error-message b/src/test/resources/reflection-and-serialization-test-error-message index a60293d3e6..a56576c62c 100644 --- a/src/test/resources/reflection-and-serialization-test-error-message +++ b/src/test/resources/reflection-and-serialization-test-error-message @@ -1,15 +1,5 @@ The class "%1$s" needs to be configured or excluded for reflection / serialization and was not mentioned in one of the following resources: -Please do one of the following: -1. add "%1$s" to serialization.json and / or reflect-config.json -2. add "%1$s" to no-reflect-and-serialization-list - -DO NOT do both. - -Option 1: -The class is serialized or reflected over. Includes "GH*" classes the are populated using Jackson. -Does not include Builders and other classes that are only used locally. - src/main/resources/META-INF/reflect-config.json - example: { @@ -34,12 +24,10 @@ src/main/resources/META-INF/serialization.json - example: "name": "%1$s" } -Option 2: -The class is not serialized or reflected over. This is less common. - src/test/resources/no-reflect-and-serialization-list - example: %1$s +Please add it to either no-reflect-and-serialization-list or to serialization.json and / or reflect-config.json