diff --git a/.github/workflows/daily-build.yml b/.github/workflows/daily-build.yml index d55b6e6b74..ee8ba28639 100644 --- a/.github/workflows/daily-build.yml +++ b/.github/workflows/daily-build.yml @@ -38,6 +38,7 @@ jobs: packageUser: ${{ github.actor }} packagePAT: ${{ secrets.GITHUB_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} TEST_MODE_ACTIVE: true run: ./gradlew clean build --stacktrace --scan --console=plain --no-daemon --continue -x project-api-tests:test @@ -235,6 +236,7 @@ jobs: packageUser: ${{ github.actor }} packagePAT: ${{ secrets.GITHUB_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} TEST_MODE_ACTIVE: true run: ./gradlew :project-api-tests:test --stacktrace --scan --console=plain --no-daemon --continue @@ -256,6 +258,7 @@ jobs: packageUser: ${{ github.actor }} packagePAT: ${{ secrets.GITHUB_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} TEST_MODE_ACTIVE: true run: ./gradlew.bat clean build --stacktrace --scan --console=plain --no-daemon -x test diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b36e3c2bc7..d1f589edc5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,6 +39,7 @@ jobs: packageUser: ${{ github.actor }} packagePAT: ${{ secrets.GITHUB_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} run: ./gradlew clean build --stacktrace --scan --console=plain --no-daemon --continue -x project-api-tests:test - name: Build Ballerina Distribution Skip Tests @@ -47,6 +48,7 @@ jobs: packageUser: ${{ github.actor }} packagePAT: ${{ secrets.GITHUB_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} run: ./gradlew clean build --stacktrace --scan --console=plain --no-daemon --continue -x test - name: Archive Ballerina ZIP uses: actions/upload-artifact@v2 diff --git a/.github/workflows/publish-release-artifacts-1.2.x.yml b/.github/workflows/publish-release-artifacts-1.2.x.yml index ec48cc5093..cab8f109b9 100644 --- a/.github/workflows/publish-release-artifacts-1.2.x.yml +++ b/.github/workflows/publish-release-artifacts-1.2.x.yml @@ -56,6 +56,7 @@ jobs: packageUser: ${{ secrets.BALLERINA_BOT_USERNAME }} packagePAT: ${{ secrets.BALLERINA_BOT_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} - name: Generate metadata json diff --git a/.github/workflows/publish-release-artifacts.yml b/.github/workflows/publish-release-artifacts.yml index 5ee607ec5f..d2b67b44d9 100644 --- a/.github/workflows/publish-release-artifacts.yml +++ b/.github/workflows/publish-release-artifacts.yml @@ -66,6 +66,7 @@ jobs: packageUser: ${{ secrets.BALLERINA_BOT_USERNAME }} packagePAT: ${{ secrets.BALLERINA_BOT_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} - name: Generate metadata json diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 0c5bc553d7..e1f172e225 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -71,6 +71,7 @@ jobs: packageUser: ${{ secrets.BALLERINA_BOT_USERNAME }} packagePAT: ${{ secrets.BALLERINA_BOT_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} run: | ./gradlew build -Pversion=${VERSION} diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 87da042fb2..f94054a6c0 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -28,6 +28,7 @@ jobs: packageUser: ${{ github.actor }} packagePAT: ${{ secrets.GITHUB_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} run: ./gradlew clean build --stacktrace --scan --console=plain --no-daemon --continue -x :ballerina:testExamples -x :project-api-tests:test @@ -50,6 +51,7 @@ jobs: packageUser: ${{ github.actor }} packagePAT: ${{ secrets.GITHUB_TOKEN }} devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} run: ./gradlew clean :ballerina:testExamples --stacktrace --scan --console=plain --no-daemon --continue -x :project-api-tests:test windows-build-without-tests: @@ -72,5 +74,6 @@ jobs: packagePAT: ${{ secrets.GITHUB_TOKEN }} JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8 devCentralToken: ${{ secrets.BALLERINA_DEV_CENTRAL_ACCESS_TOKEN }} + githubAccessToken: ${{ secrets.GITHUB_TOKEN }} ballerinaBotWorkflow: $ {{ secrets.BALLERINA_BOT_WORKFLOW }} run: ./gradlew.bat clean build --stacktrace --scan --console=plain --no-daemon --continue -x test diff --git a/ballerina-test-automation/gradle.properties b/ballerina-test-automation/gradle.properties index 624bc1a057..f87563642e 100644 --- a/ballerina-test-automation/gradle.properties +++ b/ballerina-test-automation/gradle.properties @@ -1,7 +1,7 @@ -swan-lake-latest-version=swan-lake-2201.8.0 +swan-lake-latest-version=swan-lake-2201.8.1 swan-lake-latest-spec-version=2023R1 -swan-lake-latest-version-display-text=2201.8.0 -swan-lake-latest-tool-version=1.4.0 -latest-tool-version=1.4.0 +swan-lake-latest-version-display-text=2201.8.1 +swan-lake-latest-tool-version=1.4.1 +latest-tool-version=1.4.1 1-x-channel-latest-version=1.2.13 1-x-channel-latest-spec-version=2020R1 diff --git a/examples/custom-prefetch-methods/custom_prefetch_methods.bal b/examples/custom-prefetch-methods/custom_prefetch_methods.bal index 8594179502..fddea034b9 100644 --- a/examples/custom-prefetch-methods/custom_prefetch_methods.bal +++ b/examples/custom-prefetch-methods/custom_prefetch_methods.bal @@ -40,12 +40,7 @@ isolated function bookLoaderFunction(readonly & anydata[] ids) returns BookRow[] } @graphql:ServiceConfig { - contextInit: isolated function(http:RequestContext requestContext, http:Request request) - returns graphql:Context { - graphql:Context ctx = new; - ctx.registerDataLoader("bookLoader", new dataloader:DefaultDataLoader(bookLoaderFunction)); - return ctx; - } + contextInit } service /graphql on new graphql:Listener(9090) { resource function get authors() returns Author[] { @@ -84,3 +79,9 @@ public isolated distinct service class Author { select {id: bookRow.id, title: bookRow.title}; } } + +isolated function contextInit(http:RequestContext requestContext, http:Request request) returns graphql:Context { + graphql:Context ctx = new; + ctx.registerDataLoader("bookLoader", new dataloader:DefaultDataLoader(bookLoaderFunction)); + return ctx; +} diff --git a/examples/graphql-context/graphql_context.bal b/examples/graphql-context/graphql_context.bal index 30dc8007e4..96cc33ed0e 100644 --- a/examples/graphql-context/graphql_context.bal +++ b/examples/graphql-context/graphql_context.bal @@ -11,20 +11,7 @@ type Profile record {| @graphql:ServiceConfig { // Initialization of the `graphqlContext` should be provided to the `contextInit` field. - contextInit: isolated function(http:RequestContext requestContext, http:Request request) - returns graphql:Context|error { - - // Initialize the `graphql:Context` object. - graphql:Context context = new; - - // Retrieves the header named `scope` from the `http:request` and set it to the context with - // the `scope` key. If the header does not exist, this will return an `error`, and thereby, - // the request will not be processed. - context.set("scope", check request.getHeader("scope")); - - // Finally, the context object should be returned. - return context; - } + contextInit } service /graphql on new graphql:Listener(9090) { // Defines a `Profile` field inside the service. @@ -50,3 +37,16 @@ service /graphql on new graphql:Listener(9090) { return error("Permission denied"); } } + +isolated function contextInit(http:RequestContext requestContext, http:Request request) returns graphql:Context|error { + // Initialize the `graphql:Context` object. + graphql:Context context = new; + + // Retrieves the header named `scope` from the `http:request` and set it to the context with + // the `scope` key. If the header does not exist, this will return an `error`, and thereby, + // the request will not be processed. + context.set("scope", check request.getHeader("scope")); + + // Finally, the context object should be returned. + return context; +} diff --git a/examples/graphql-dataloader/graphql_dataloader.bal b/examples/graphql-dataloader/graphql_dataloader.bal index 99246efbfc..bbc8737fa4 100644 --- a/examples/graphql-dataloader/graphql_dataloader.bal +++ b/examples/graphql-dataloader/graphql_dataloader.bal @@ -48,14 +48,7 @@ isolated function bookLoaderFunction(readonly & anydata[] ids) returns BookRow[] } @graphql:ServiceConfig { - contextInit: isolated function(http:RequestContext requestContext, http:Request request) - returns graphql:Context { - graphql:Context ctx = new; - // Register the dataloader with the context using a unique name. - // A defult implementation of the dataloader is used here. - ctx.registerDataLoader("bookLoader", new dataloader:DefaultDataLoader(bookLoaderFunction)); - return ctx; - } + contextInit } service /graphql on new graphql:Listener(9090) { resource function get authors() returns Author[] { @@ -93,3 +86,11 @@ public isolated distinct service class Author { select {id: bookRow.id, title: bookRow.title}; } } + +isolated function contextInit(http:RequestContext requestContext, http:Request request) returns graphql:Context { + graphql:Context ctx = new; + // Register the dataloader with the context using a unique name. + // A defult implementation of the dataloader is used here. + ctx.registerDataLoader("bookLoader", new dataloader:DefaultDataLoader(bookLoaderFunction)); + return ctx; +} diff --git a/examples/index.json b/examples/index.json index 40b9b8074b..0863c62cd5 100644 --- a/examples/index.json +++ b/examples/index.json @@ -2426,6 +2426,21 @@ "disablePlayground": true, "isLearnByExample": false }, + { + "name": "Hierarchical resource paths", + "url": "graphql-hierarchical-resource-paths", + "verifyBuild": true, + "verifyOutput": false, + "disablePlayground": true, + "isLearnByExample": false + } + ] + }, + { + "title": " GraphQL service advanced", + "column": 1, + "category": "Network libraries", + "samples": [ { "name": "Context object", "url": "graphql-context", @@ -2483,21 +2498,6 @@ "disablePlayground": true, "isLearnByExample": false }, - { - "name": "Hierarchical resource paths", - "url": "graphql-hierarchical-resource-paths", - "verifyBuild": true, - "verifyOutput": false, - "disablePlayground": true, - "isLearnByExample": false - } - ] - }, - { - "title": " GraphQL service advanced", - "column": 1, - "category": "Network libraries", - "samples": [ { "name": "Dataloader", "url": "graphql-dataloader", diff --git a/examples/mysql-prerequisite/setup_database.bal b/examples/mysql-prerequisite/setup_database.bal index d25e2ce08a..953074b507 100644 --- a/examples/mysql-prerequisite/setup_database.bal +++ b/examples/mysql-prerequisite/setup_database.bal @@ -62,10 +62,12 @@ public function main() returns sql:Error? { );`); // Adds the records to the `sales_order` table. - _ = check mysqlClient->execute(`INSERT INTO inventory VALUES - ("A-123", "Lemonade", "Beyonce", 18.98, 10);`); - _ = check mysqlClient->execute(`INSERT INTO inventory VALUES - ("A-321", "Renaissance", "Beyonce", 24.98, 100);`); + _ = check mysqlClient->execute(`INSERT INTO MUSIC_STORE.sales_order VALUES + ("S-123", "2022-12-09", "A-123", 2);`); + _ = check mysqlClient->execute(`INSERT INTO MUSIC_STORE.sales_order VALUES + ("S-321", "2022-12-09", "A-321", 1);`); + _ = check mysqlClient->execute(`INSERT INTO MUSIC_STORE.sales_order VALUES + ("S-456", "2022-12-10", "A-321", 3);`); check mysqlClient.close(); } diff --git a/examples/programs-and-modules/programs_and_modules.bal b/examples/programs-and-modules/programs_and_modules.bal index 2eb647f8b6..e785a8ea83 100644 --- a/examples/programs-and-modules/programs_and_modules.bal +++ b/examples/programs-and-modules/programs_and_modules.bal @@ -1,5 +1,6 @@ // This import declaration binds the prefix `io` to the `ballerina/io` package. // The prefix by default comes from the last part of the package name. + // The `ballerina` org name is reserved for the Ballerina library packages. import ballerina/io; diff --git a/examples/sequence-diagrams/sequence_diagrams.bal b/examples/sequence-diagrams/sequence_diagrams.bal index 4980684906..3da030c426 100644 --- a/examples/sequence-diagrams/sequence_diagrams.bal +++ b/examples/sequence-diagrams/sequence_diagrams.bal @@ -6,11 +6,11 @@ import ballerina/io; public function main() returns error? { // The diagram also has a lifeline for each client object parameter or variable in // the initialization section, representing the remote system to which the client object is sending messages. - http:Client cl = check new ("https://www.mocky.io"); + http:Client cl = check new ("https://run.mocky.io"); // Each remote method call on a client object is represented as a horizontal line // between the lifeline of the worker making the call and the remote system. - string payload = check cl->get("/v2/5ae082123200006b00510c3d/"); + string payload = check cl->get("/v3/7240398e-0435-4457-91b0-0c862f10563f/"); io:println(payload); return; diff --git a/gradle.properties b/gradle.properties index 0048569daf..3496f562f8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ group=org.ballerinalang version=2201.8.0-SNAPSHOT codeName=swan-lake -ballerinaLangVersion=2201.8.0-20230830-220400-8a7556d8 +ballerinaLangVersion=2201.8.0-20231001-002700-760d4e3b ballerinaJreVersion=2.0.0 dependencyJREVersion=jdk-17.0.7+7-jre specVersion=2023R1 @@ -75,7 +75,7 @@ persistToolVersion=1.2.0-20230908-152500-2ba8c45 # Dev Tools devToolsVersion=1.2.1-20230914-153500-664cd40 -ballerinaCommandVersion=1.4.0 +ballerinaCommandVersion=1.4.1 # GraphQL Tool graphqlVersion=0.8.0-20230914-153500-87f60d6 diff --git a/project-api-tests/src/test/java/org/ballerina/projectapi/MavenCustomRepoTest.java b/project-api-tests/src/test/java/org/ballerina/projectapi/MavenCustomRepoTest.java new file mode 100644 index 0000000000..d10aae3dc3 --- /dev/null +++ b/project-api-tests/src/test/java/org/ballerina/projectapi/MavenCustomRepoTest.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://wso2.com). + * + * Licensed 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. + */ + +package org.ballerina.projectapi; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + + +import static org.ballerina.projectapi.MavenCustomRepoTestUtils.createSettingToml; +import static org.ballerina.projectapi.MavenCustomRepoTestUtils.deleteArtifacts; +import static org.ballerina.projectapi.MavenCustomRepoTestUtils.deleteFiles; +import static org.ballerina.projectapi.MavenCustomRepoTestUtils.getEnvVariables; +import static org.ballerina.projectapi.MavenCustomRepoTestUtils.getString; +import static org.ballerina.projectapi.TestUtils.DISTRIBUTION_FILE_NAME; +import static org.ballerina.projectapi.TestUtils.OUTPUT_CONTAIN_ERRORS; +import static org.ballerina.projectapi.TestUtils.executeBuildCommand; +import static org.ballerina.projectapi.TestUtils.executePullCommand; +import static org.ballerina.projectapi.TestUtils.executePushCommand; + +/** + * Tests related to Maven repositories. + */ +public class MavenCustomRepoTest { + + private static final String org = "bctestorg"; + private static final String packagename = "pact"; + private static final String version = "0.2.0"; + private static final String GITHUB_REPO_ID = "github1"; + private Path actualHomeDirectory; + private Path tempWorkspaceDirectory; + private Path actualHomeDirectoryClone; + private Map envVariables; + + @BeforeClass() + public void setUp() throws IOException { + TestUtils.setupDistributions(); + actualHomeDirectory = Paths.get(System.getProperty("user.home")).resolve(".ballerina"); + actualHomeDirectoryClone = Files.createTempDirectory("bal-test-integration-packaging-home-") + .resolve(".ballerina"); + Files.walkFileTree(actualHomeDirectory, + new MavenCustomRepoTest.Copy(actualHomeDirectory, actualHomeDirectoryClone)); + deleteFiles(actualHomeDirectory, true); + tempWorkspaceDirectory = Files.createTempDirectory("bal-test-integration-packaging-workspace-"); + + createSettingToml(actualHomeDirectory); + System.setProperty("user.home", actualHomeDirectory.getParent().toString()); + envVariables = getEnvVariables(); + + // Copy test resources to temp workspace directory + try { + URI testResourcesURI = Objects.requireNonNull(getClass().getClassLoader() + .getResource("maven-repos")).toURI(); + Files.walkFileTree(Paths.get(testResourcesURI), new MavenCustomRepoTest.Copy(Paths.get(testResourcesURI), + this.tempWorkspaceDirectory)); + } catch (URISyntaxException e) { + Assert.fail("error loading resources"); + } + } + + @Test(description = "Push package to Github packages") + public void testPushBalaGithub() throws IOException, InterruptedException { + List args = new ArrayList<>(); + args.add("--repository=" + GITHUB_REPO_ID); + Process build = executePushCommand(DISTRIBUTION_FILE_NAME, this.tempWorkspaceDirectory.resolve(packagename), + args, this.envVariables); + String buildErrors = getString(build.getErrorStream()); + if (!buildErrors.isEmpty()) { + Assert.fail(OUTPUT_CONTAIN_ERRORS + buildErrors); + } + + String buildOutput = getString(build.getInputStream()); + Assert.assertTrue(buildOutput.contains("Successfully pushed target/bala/" + org + "-" + + packagename + "-any-" + version + ".bala to " + "'" + GITHUB_REPO_ID + "' repository.")); + } + + @Test(description = "Pull package from Github packages", dependsOnMethods = "testPushBalaGithub") + public void testPullBalaGithub() throws IOException, InterruptedException { + List args = new ArrayList<>(); + args.add(org + "/" + packagename + ":" + version); + args.add("--repository=" + GITHUB_REPO_ID); + Process build = executePullCommand(DISTRIBUTION_FILE_NAME, this.tempWorkspaceDirectory.resolve(packagename), + args, this.envVariables); + String buildErrors = getString(build.getErrorStream()); + if (!buildErrors.isEmpty()) { + Assert.fail(OUTPUT_CONTAIN_ERRORS + buildErrors); + } + + String buildOutput = getString(build.getInputStream()); + Assert.assertTrue(buildOutput.contains("Successfully pulled the package from the custom repository")); + + Path packagePath = this.actualHomeDirectory.resolve("repositories") + .resolve(GITHUB_REPO_ID).resolve("bala").resolve(org).resolve(packagename).resolve(version); + Assert.assertTrue(Files.exists(packagePath.resolve("any"))); + deleteFiles(this.actualHomeDirectory.resolve("repositories").resolve(GITHUB_REPO_ID), false); + } + + @Test(description = "Build a package offline using a module from Github packages", + dependsOnMethods = "testPullBalaGithub") + public void testBuildBalaGithubOffline() throws IOException, InterruptedException { + List args = new ArrayList<>(); + args.add("--offline=true"); + Process build = executeBuildCommand(DISTRIBUTION_FILE_NAME, this.tempWorkspaceDirectory + .resolve("test-resolution"), + args, this.envVariables); + String buildErrors = getString(build.getErrorStream()); + Assert.assertTrue(buildErrors.contains("cannot resolve module '" + org + "/pact as _'")); + } + + @Test(description = "Build a package Online using a module from Github packages", + dependsOnMethods = "testBuildBalaGithubOffline") + public void testBuildBalaGithubOnline() throws IOException, InterruptedException { + List args = new ArrayList<>(); + args.add("--offline=false"); + Process build = executeBuildCommand(DISTRIBUTION_FILE_NAME, this.tempWorkspaceDirectory + .resolve("test-resolution"), + args, this.envVariables); + String buildErrors = getString(build.getErrorStream()); + if (!buildErrors.isEmpty()) { + Assert.fail(OUTPUT_CONTAIN_ERRORS + buildErrors); + } + + String buildOutput = getString(build.getInputStream()); + Assert.assertTrue(buildOutput.contains("Generating executable\n\ttarget/bin/test.jar")); + } + + @AfterClass + private void cleanup() throws IOException { + deleteFiles(actualHomeDirectory, true); + Files.walkFileTree(actualHomeDirectoryClone, + new MavenCustomRepoTest.Copy(actualHomeDirectoryClone, actualHomeDirectory)); + deleteFiles(actualHomeDirectoryClone, false); + deleteFiles(tempWorkspaceDirectory, false); + deleteArtifacts(org, packagename); + } + + + + /** + * Copy test resources to temp directory. + */ + static class Copy extends SimpleFileVisitor { + private final Path fromPath; + private final Path toPath; + private final StandardCopyOption copyOption; + + Copy(Path fromPath, Path toPath, StandardCopyOption copyOption) { + this.fromPath = fromPath; + this.toPath = toPath; + this.copyOption = copyOption; + } + + Copy(Path fromPath, Path toPath) { + this(fromPath, toPath, StandardCopyOption.REPLACE_EXISTING); + } + + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + + Path targetPath = toPath.resolve(fromPath.relativize(dir).toString()); + if (!Files.exists(targetPath)) { + Files.createDirectory(targetPath); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + + Files.copy(file, toPath.resolve(fromPath.relativize(file).toString()), copyOption); + return FileVisitResult.CONTINUE; + } + } +} diff --git a/project-api-tests/src/test/java/org/ballerina/projectapi/MavenCustomRepoTestUtils.java b/project-api-tests/src/test/java/org/ballerina/projectapi/MavenCustomRepoTestUtils.java new file mode 100644 index 0000000000..b4aa7dfdd2 --- /dev/null +++ b/project-api-tests/src/test/java/org/ballerina/projectapi/MavenCustomRepoTestUtils.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://wso2.com). + * + * Licensed 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. + */ + +package org.ballerina.projectapi; + +import okhttp3.OkHttpClient; +import okhttp3.Request; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +/** + * Utility class for maven repository tests. + */ +public class MavenCustomRepoTestUtils { + + /** + * Create Settings.toml inside the home repository. + * @param dirPath folder path to the settings toml + * @throws IOException i/o exception when writing to file + */ + static void createSettingToml(Path dirPath) throws IOException { + String content = "[[repository.maven]]\n " + + "id = \"github1\"\n " + + "url = \"https://maven.pkg.github.com/ballerina-platform/ballerina-release\"\n " + + "username = \"ballerina-platform\"\n " + + "accesstoken = \"" + getGithubToken() + "\"\n"; + Files.write(dirPath.resolve("Settings.toml"), content.getBytes(), StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING); + } + + /** + * Get access token of GitHub required to push the module. + * + * @return token required to push the module. + */ + private static String getGithubToken() { + return System.getenv("githubAccessToken"); + } + + /** + * Get environment variables and add ballerina_home as a env variable the tmp directory. + * + * @return env directory variable array + */ + static Map getEnvVariables() { + Map envVarMap = System.getenv(); + Map retMap = new HashMap<>(); + envVarMap.forEach(retMap::put); + return retMap; + } + + /** + * Convert input stream to string. + * + * @param outputs input stream + * @return converted string + * @throws IOException Error when reading from input stream + */ + static String getString(InputStream outputs) throws IOException { + try (BufferedReader br = new BufferedReader(new InputStreamReader(outputs))) { + Stream logLines = br.lines(); + String generatedLog = logLines.collect(Collectors.joining("\n")); + logLines.close(); + return generatedLog; + } + } + + /** + * Delete files inside directories. + * + * @param dirPath directory path + * @param deleteDirContentOnly delete only the content inside the directory + * @throws IOException throw an exception if an issue occurs + */ + static void deleteFiles(Path dirPath, boolean deleteDirContentOnly) throws IOException { + Files.walk(dirPath) + .sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + if (deleteDirContentOnly) { + Files.createDirectories(dirPath); + } + } + + /** + * Delete artifacts from GitHub. + * @param org organization name + * @param packagename package name + */ + static void deleteArtifacts(String org, String packagename) throws IOException { + OkHttpClient client = new OkHttpClient(); + Request request = new Request.Builder() + .url("https://api.github.com/orgs/ballerina-platform/packages/maven/" + org + "." + packagename) + .header("Accept", "application/vnd.github+json") + .header("Authorization", "Bearer " + getGithubToken()) + .header("X-GitHub-Api-Version", "2022-11-28") + .delete() + .build(); + client.newCall(request).execute(); + } +} diff --git a/project-api-tests/src/test/resources/maven-repos/pact/.devcontainer.json b/project-api-tests/src/test/resources/maven-repos/pact/.devcontainer.json new file mode 100644 index 0000000000..86079a3084 --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/pact/.devcontainer.json @@ -0,0 +1,4 @@ +{ + "image": "ballerina/ballerina-devcontainer:2201.6.0", + "extensions": ["WSO2.ballerina"], +} diff --git a/project-api-tests/src/test/resources/maven-repos/pact/.gitignore b/project-api-tests/src/test/resources/maven-repos/pact/.gitignore new file mode 100644 index 0000000000..c874bf7adb --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/pact/.gitignore @@ -0,0 +1,2 @@ +generated +Config.toml diff --git a/project-api-tests/src/test/resources/maven-repos/pact/Ballerina.toml b/project-api-tests/src/test/resources/maven-repos/pact/Ballerina.toml new file mode 100644 index 0000000000..7ca90e6d1b --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/pact/Ballerina.toml @@ -0,0 +1,7 @@ +[package] +org = "bctestorg" +name = "pact" +version = "0.2.0" + +[build-options] +observabilityIncluded = true diff --git a/project-api-tests/src/test/resources/maven-repos/pact/main.bal b/project-api-tests/src/test/resources/maven-repos/pact/main.bal new file mode 100644 index 0000000000..6d0ccb5ba6 --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/pact/main.bal @@ -0,0 +1,3 @@ + +public function main() { +} diff --git a/project-api-tests/src/test/resources/maven-repos/pact/package.md b/project-api-tests/src/test/resources/maven-repos/pact/package.md new file mode 100644 index 0000000000..3806222f94 --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/pact/package.md @@ -0,0 +1 @@ +jsjj diff --git a/project-api-tests/src/test/resources/maven-repos/test-resolution/.devcontainer.json b/project-api-tests/src/test/resources/maven-repos/test-resolution/.devcontainer.json new file mode 100644 index 0000000000..86079a3084 --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/test-resolution/.devcontainer.json @@ -0,0 +1,4 @@ +{ + "image": "ballerina/ballerina-devcontainer:2201.6.0", + "extensions": ["WSO2.ballerina"], +} diff --git a/project-api-tests/src/test/resources/maven-repos/test-resolution/.gitignore b/project-api-tests/src/test/resources/maven-repos/test-resolution/.gitignore new file mode 100644 index 0000000000..7512ebe232 --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/test-resolution/.gitignore @@ -0,0 +1,3 @@ +target +generated +Config.toml diff --git a/project-api-tests/src/test/resources/maven-repos/test-resolution/Ballerina.toml b/project-api-tests/src/test/resources/maven-repos/test-resolution/Ballerina.toml new file mode 100644 index 0000000000..deea16ec3e --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/test-resolution/Ballerina.toml @@ -0,0 +1,13 @@ +[package] +org = "bctestorg" +name = "test" +version = "0.1.0" + +[build-options] +observabilityIncluded = true + + [[dependency]] + org = "bctestorg" + name = "pact" + version = "0.2.0" + repository="github1" diff --git a/project-api-tests/src/test/resources/maven-repos/test-resolution/main.bal b/project-api-tests/src/test/resources/maven-repos/test-resolution/main.bal new file mode 100644 index 0000000000..69d7f41a9f --- /dev/null +++ b/project-api-tests/src/test/resources/maven-repos/test-resolution/main.bal @@ -0,0 +1,6 @@ +import bctestorg/pact as _; +import ballerina/io; + +public function main() { + io:println("Hello World!"); +} diff --git a/project-api-tests/src/test/resources/testng.xml b/project-api-tests/src/test/resources/testng.xml index bdb1d2cd36..0f1a679212 100644 --- a/project-api-tests/src/test/resources/testng.xml +++ b/project-api-tests/src/test/resources/testng.xml @@ -22,5 +22,8 @@ + + +