Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Update Gradle wrapper #79

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Organizations service for the Moderne platform

This repository template is a service that can be run by [Moderne](https://www.moderne.io/) customers to inform the platform about the organizational structure of their
repositories. In the reference implementation provided here, the [organizations are determined by a hardcoded JSON file](/src/main/resources/ownership.json)
plus an "ALL" group that contains all repositories. This is meant to be customized per organization.
repositories. In the reference implementation provided here, the [repositories and their organization hierarchy are determined by a hardcoded CSV file](/src/main/resources/repos.csv)
plus an "ALL" organization that contains all repositories. This is meant to be customized per organization.

The GraphQL schema for this service is defined
in [moderne-organizations.graphqls](src/main/resources/schema/moderne-organizations.graphqls), and serves as the
contract for what Moderne expects a customized organization service to provide.

If there is no organization service [configured for your agent](https://docs.moderne.io/administrator-documentation/on-premise-agent/configure-organizations-service), Moderne will fall back on a single shared "ALL" named
repository group. This is convenient for onboarding initially, but as a customer grows and brings more teams onto the
If there is no organization service [configured for your agent](https://docs.moderne.io/administrator-documentation/on-premise-agent/configure-organizations-service), Moderne will fall back on a single organization named "ALL".
This is convenient for onboarding initially, but as a customer grows and brings more teams onto the
platform, they should supply organizational hierarchy to help developers action only their assets.

## Getting started
Expand All @@ -22,9 +22,7 @@ platform, they should supply organizational hierarchy to help developers action

```graphql
query testOrgService {
organizations(
repository: {origin: "github.com", path: "openrewrite/rewrite", branch: "main"}
) {
allOrganizations {
...Org
}
userOrganizations(user: {email: "[email protected]"}) {
Expand All @@ -44,15 +42,17 @@ fragment Org on Organization {

## Customizing the service

### Creating organizations
You are free to customize the implementation in any way as long as the API contract is implemented correctly.

The easiest way to create an organization is to use the Moderne platform to create a [repository group](https://docs.moderne.io/references/managing-repository-groups)
and then [export it](https://docs.moderne.io/references/managing-repository-groups#how-to-export-repository-groups-json).
This will result in a JSON file that you can either use to replace the [ownership.json](/src/main/resources/ownership.json)
file with or use to create a separate JSON file to have multiple organizations.
### Creating repos.csv

If you create a new JSON file, you'll need to update the [OrganizationDataFetcher.java](/src/main/java/io/moderne/organizations/OrganizationDataFetcher.java)
file to add a new `List<OrganizationRepositories>` and concatenate it with the existing `ownership` list.
Use [repo-fetchers](repo-fetchers/README.md) to generate a (partial) repos.csv and add your organization structure.

The org structure is represented in a series of columns `org1..orgN` where `N` is the deepest organization structure. Not every repository needs to have the same depth of organizational structure. To make the resultant CSV renderable in GitHub, you can right-align org structure to `orgN` as shown in the image below:

<img width="771" alt="image" src="https://github.com/moderneinc/moderne-organizations-dx/assets/1697736/d0d8cd92-47ea-488c-8256-52117636bcae">

There is repetition in organizational hierarchy in this format. The reference implementation validates the internal consistency of those organizational repositories across CSV lines.

### Commit options
The `commitOptions` field on the `Organization` type is a list of strings that represent the commit options that are
Expand Down
24 changes: 8 additions & 16 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ buildscript {
}

plugins {
id("org.springframework.boot") version "2.7.2"
id("org.springframework.boot") version "3.2.2"
java
id("nebula.release") version "15.3.1"
id("nebula.maven-nebula-publish") version "18.2.0"
Expand Down Expand Up @@ -51,12 +51,6 @@ java {

configurations {
all {
resolutionStrategy.eachDependency {
if(requested.group == "org.yaml" && requested.name == "snakeyaml") {
useVersion("1.33")
because("snakeyaml 2.0 doesn't work with Spring Boot.")
}
}
resolutionStrategy {
cacheChangingModulesFor(0, TimeUnit.SECONDS)
cacheDynamicVersionsFor(0, TimeUnit.SECONDS)
Expand All @@ -66,8 +60,9 @@ configurations {

dependencies {
implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
implementation(platform("org.springframework.cloud:spring-cloud-dependencies:2021.0.2"))
implementation(platform("org.springframework.cloud:spring-cloud-dependencies:2023.0.0"))
implementation(platform("io.netty:netty-bom:4.1.100.Final"))
implementation(platform("com.netflix.graphql.dgs:graphql-dgs-platform:latest.release"))

implementation("org.openrewrite:rewrite-core:latest.release")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-csv")
Expand All @@ -76,19 +71,16 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("io.micrometer:micrometer-core:latest.release")

implementation("com.graphql-java:graphql-java:18+")
implementation("com.graphql-java:graphql-java-extended-scalars:18+")
implementation("com.graphql-java:graphql-java")
implementation("com.graphql-java:graphql-java-extended-scalars")

implementation("org.springframework.boot:spring-boot-starter-actuator")

implementation("com.netflix.graphql.dgs:graphql-dgs-webflux-starter:5+") {
exclude(module = "snakeyaml")
}
implementation("com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer:5+") {
exclude(module = "snakeyaml")
}
implementation("com.netflix.graphql.dgs:graphql-dgs-webflux-starter")
implementation("com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer")

implementation("io.micrometer:micrometer-registry-prometheus:latest.release")
implementation("io.micrometer:micrometer-registry-prometheus-simpleclient:latest.release")

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation(platform("org.junit:junit-bom:latest.release"))
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026
distributionSha256Sum=a4b4158601f8636cdeeab09bd76afb640030bb5b144aafe261a5e8af027dc612
2 changes: 1 addition & 1 deletion gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand Down
20 changes: 10 additions & 10 deletions gradlew.bat
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand All @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand Down
82 changes: 82 additions & 0 deletions repo-fetchers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
## Repo Fetchers

This directory contains three bash scripts that can be used to fetch repositories. Below are the details of each script along with examples of how to invoke them and their required/optional arguments.

### `bitbucket-data-center.sh`

This script fetches all repositories from a Bitbucket Data Center instance and assumes the project as the organization.

#### Usage
```sh
./bitbucket-data-center.sh <bitbucket_url>
```

#### Description
This script fetches all repositories from the specified Bitbucket Data Center URL. If the `AUTH_TOKEN` environment variable is set, it will be used for authentication.

#### Example
To fetch all repositories from a Bitbucket Data Center instance:
```sh
./bitbucket-data-center.sh https://my-bitbucket.com/stash
```

### `bitbucket-cloud.sh`

This script fetches all repositories from a Bitbucket Cloud workspace and assumes the workspace as the organization.
Note: Email addresses do not work, you need your Bitbucket username which you can find (here)[https://bitbucket.org/account/settings/]

#### Using paremeters
```sh
./bitbucket-cloud.sh -u <username> -p <app_password> <workspace> > repos.csv
```

#### Using env vars
```sh
env BITBUCKET_USERNAME="<username>" BITBUCKET_APP_PASSWORD="<app_password>" ./bitbucket-cloud.sh <workspace>
```

#### Description
This script fetches all repositories from the specified Bitbucket Cloud workspace.

#### Example
To fetch all repositories from a Bitbucket Data Center instance:
```sh
./bitbucket-cloud.sh -u moderne -p secret moderneinc > repos.csv
```

### `gitlab.sh`

This script fetches all repositories from a GitLab instance or a specific group within a GitLab instance using the (sub)group path as the organization

#### Usage
```sh
./gitlab.sh [-g <group>] [-h <gitlab_domain>]
```

#### Description
This script fetches all repositories from a GitLab instance or a specific group within a GitLab instance. The `AUTH_TOKEN` environment variable must be set for authentication. The `-g` option specifies a group to fetch repositories from. The `-h` option specifies the GitLab domain (defaults to `https://gitlab.com` if not provided).

#### Example
To fetch all repositories from a specific group on a custom GitLab domain:
```sh
./gitlab.sh -g my-group -h https://my-gitlab.com
```

### `github.sh`

This script fetches all repositories from a GitHub organization.

#### Usage
```sh
./github.sh <organization_name>
```

#### Description
This script fetches all repositories from the specified GitHub organization. The `GITHUB_TOKEN` environment variable must be set for authentication.

#### Example
To fetch all repositories from a GitHub organization:
```sh
./github.sh my-organization
```

67 changes: 67 additions & 0 deletions repo-fetchers/bitbucket-cloud.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash

# Parse command-line arguments
while getopts ":u:p:" opt; do
case ${opt} in
u )
USERNAME=$OPTARG
;;
p )
APP_PASSWORD=$OPTARG
;;
\? )
echo "Usage: $0 <workspace> -u <username> -p <password>"
exit 1
;;
: )
echo "Invalid option: $OPTARG requires an argument" 1>&2
exit 1
;;
esac
done
shift $((OPTIND -1))

# Set workspace from positional argument
WORKSPACE=$1

# Check if USERNAME and APP_PASSWORD are provided via command line or environment variables
if [[ -z "$USERNAME" ]]; then
USERNAME=$BITBUCKET_USERNAME
fi

if [[ -z "$APP_PASSWORD" ]]; then
APP_PASSWORD=$BITBUCKET_APP_PASSWORD
fi

# Check if required variables are set
if [[ -z "$USERNAME" || -z "$APP_PASSWORD" || -z "$WORKSPACE" ]]; then
echo "Error: Please provide username, password, and workspace." >&2
echo "Usage: $0 <workspace> -u <username> -p <password>" >&2
exit 1
fi

BASE_URL="https://api.bitbucket.org/2.0/repositories/$WORKSPACE"

echo "cloneUrl,branchName"

# Start fetching repositories
NEXT_URL=$BASE_URL

while [ -n "$NEXT_URL" ]; do
RESPONSE=$(curl -s -u "$USERNAME:$APP_PASSWORD" "$NEXT_URL")

# Extract repository data and append to CSV file
echo $RESPONSE | jq -r '
.values[] |
(.links.clone[] | select(.name=="https") | .href) as $cloneUrl |
.mainbranch.name as $branchName |
.workspace.name as $organization |
"\($cloneUrl),\($branchName),\($organization)"' |
while IFS=, read -r cloneUrl branchName organization; do
cleanUrl=$(echo "$cloneUrl" | sed -E 's|https://[^@]+@|https://|')
echo "$cleanUrl,$branchName,$organization"
done

# Get the next URL
NEXT_URL=$(echo $RESPONSE | sed -e "s:${USERNAME}@::g" | jq -r '.next // empty')
done
32 changes: 32 additions & 0 deletions repo-fetchers/bitbucket-data-center.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash


if [ -z "$1" ]; then
echo "Usage: $0 <bitbucket_url>"
echo "Example: $0 https://my-bitbucket.com/stash"
exit 1
fi

bitbucket_url=$1
auth_header=""

if [ -n "$AUTH_TOKEN" ]; then
auth_header="Authorization: Bearer $AUTH_TOKEN"
fi

ALL_REPOS=$(curl -s -X GET -H "Content-Type: application/json" -H "$auth_header" "$bitbucket_url/rest/api/1.0/repos"| jq -r '.values[] | [.slug, .project.key, (.links.clone[] | select(.name == "http").href)] | @csv')
if [ $? -ne 0 ]; then
echo "Error occurred while retrieving repository list."
exit 1
fi

echo "cloneUrl,branch,org"
for REPO in $ALL_REPOS; do
IFS=',' read -r repo project cloneUrl <<< "$REPO"
repo="${repo//\"/}"
project="${project//\"/}"
cloneUrl="${cloneUrl//\"/}"
branch=$(curl -s -X GET -H "Content-Type: application/json" -H "$auth_header" "$bitbucket_url/rest/api/latest/projects/$project/repos/$repo/default-branch" | jq -r '.displayId')

echo "$cloneUrl,$branch,$project"
done
19 changes: 19 additions & 0 deletions repo-fetchers/github.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

if [ -z "$1" ]; then
echo "Usage: $0 <org>"
echo "Example: $0 openrewrite"
exit 1
fi

organization=$1

# JQ
# gh repo list "$organization" \
# --json url,defaultBranchRef \
# --jq '["cloneUrl","branch"], (.[] | [.url, .defaultBranchRef.name]) | @csv'

# GH CLI
gh repo list "$organization" \
--json url,defaultBranchRef \
--template '{{"cloneUrl,branch\n"}}{{range .}}{{.url}}{{","}}{{.defaultBranchRef.name}}{{","}}{{"'$organization'"}}{{"\n"}}{{end}}'
Loading