Skip to content

Commit

Permalink
chore: prepare 2.48.1 (#1816)
Browse files Browse the repository at this point in the history
  • Loading branch information
jachro authored Dec 7, 2023
2 parents 3a7bd7c + d2d9538 commit 7dcab35
Show file tree
Hide file tree
Showing 31 changed files with 917 additions and 719 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import io.renku.graph.model.testentities._
import io.renku.http.client.AccessToken
import io.renku.http.rest.Links
import io.renku.http.server.EndpointTester.{JsonOps, jsonEntityDecoder}
import io.renku.webhookservice.model
import org.http4s.Status._
import org.scalatest.EitherValues

Expand Down Expand Up @@ -77,11 +76,7 @@ class CommitHistoryChangesSpec
gitLabStub.replaceCommits(project.id, newCommits.toList: _*)
mockCommitDataOnTripleGenerator(project, toPayloadJsonLD(projectWithNewData), newCommits)

webhookServiceClient
.POST("webhooks/events", model.HookToken(project.id), GitLab.pushEvent(project, newCommits.last))
.status shouldBe Accepted

`data in the Triples Store`(project, newCommits, user.accessToken)
`data in the Triples Store`(project, newCommits.last, user.accessToken)

waitForAllEventsInFinalState(project.id)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import io.renku.graph.model.events.EventStatus.TriplesStore
import io.renku.graph.model.projects.Role
import io.renku.graph.model.testentities.cliShapedPersons
import io.renku.graph.model.testentities.generators.EntitiesGenerators._
import io.renku.webhookservice.model.HookToken
import org.http4s.Status._
import tooling.{AcceptanceSpec, ApplicationServices}

class CommitSyncFlowsSpec extends AcceptanceSpec with ApplicationServices with TSProvisioning with TypeSerializers {
Expand Down Expand Up @@ -62,14 +60,6 @@ class CommitSyncFlowsSpec extends AcceptanceSpec with ApplicationServices with T
`GET <triples-generator>/projects/:id/commits/:id returning OK with some triples`(project, nonMissedCommitId)
`GET <triples-generator>/projects/:id/commits/:id returning OK with some triples`(project, missedCommitId)

And("access token is present")
givenAccessTokenPresentFor(project, user.accessToken)

When("a Push Event arrives for the non missed event")
webhookServiceClient
.POST("webhooks/events", HookToken(project.id), data.GitLab.pushEvent(project, nonMissedCommitId))
.status shouldBe Accepted

And("relevant commit events are processed")
`data in the Triples Store`(project, nonMissedCommitId, user.accessToken)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,7 @@ class EventFlowsSpec extends AcceptanceSpec with ApplicationServices with TSProv
And("triples are generated by the Remote Triples Generator")
`GET <triples-generator>/projects/:id/commits/:id returning OK with some triples`(project, commitId)

And("access token is present")
givenAccessTokenPresentFor(project, user.accessToken)

When("a Push Event arrives")
webhookServiceClient
.POST("webhooks/events", HookToken(project.id), data.GitLab.pushEvent(project, commitId))
.status shouldBe Accepted

And("commit events are processed")
And("a Push Event arrives and commit events are processed")
`data in the Triples Store`(project, commitId, user.accessToken)

Then(s"all the events should get the $TriplesStore status in the Event Log")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ class ProjectStatusResourceSpec
CommitsCount(numberOfEvents.value)
).map(addMemberWithId(memberUser.id, Role.Owner)).generateOne

Scenario("Call be a user who is not a member of the project") {
Scenario("Call by a user who is not a member of the project") {

Given("there's no webhook for a given project in GitLab")
gitLabStub.addProject(project)

When("there's no webhook for a given project in GitLab")
And("project hasn't been activated (no trace of it in the EL)")

Given("the user is authenticated")
And("the user is authenticated")
val someAuthUser = authUsers.generateOne
gitLabStub.addAuthenticated(someAuthUser)

Expand All @@ -76,21 +76,19 @@ class ProjectStatusResourceSpec
gitLabStub.addAuthenticated(memberUser)
val commitId = commitIds.generateOne
gitLabStub.replaceCommits(project.id, commitId)
// making the triples generation be happy and not throwing exceptions to the logs
`GET <triples-generator>/projects/:id/commits/:id returning OK with some triples`(project, commitId)
mockCommitDataOnTripleGenerator(project, toPayloadJsonLD(project), commitId)

webhookServiceClient.`POST projects/:id/webhooks`(project.id, memberUser.accessToken).status shouldBe Created

Then("the non-member user should get OK with 'activated' = true")
eventually {
val authUserResponse =
webhookServiceClient.`GET projects/:id/events/status`(project.id, someAuthUser.accessToken)
authUserResponse.status shouldBe Ok
authUserResponse.jsonBody.hcursor.downField("activated").as[Boolean].value shouldBe true
val response = webhookServiceClient.`GET projects/:id/events/status`(project.id, someAuthUser.accessToken)
response.status shouldBe Ok
response.jsonBody.hcursor.downField("activated").as[Boolean].value shouldBe true
}
}

Scenario("Call be a user who is a member of the project") {
Scenario("Call by a user who is a member of the project") {

When("there's no webhook for a given project in GitLab")
gitLabStub.addProject(project)
Expand All @@ -106,8 +104,11 @@ class ProjectStatusResourceSpec
When("there's a webhook created for the project")
And("there are events under processing")
val allCommitIds = commitIds.generateNonEmptyList(min = numberOfEvents, max = numberOfEvents)
gitLabStub.setupProject(project, allCommitIds.toList: _*)
gitLabStub.replaceCommits(project.id, allCommitIds.toList: _*)
mockCommitDataOnTripleGenerator(project, toPayloadJsonLD(project), allCommitIds)

webhookServiceClient.`POST projects/:id/webhooks`(project.id, memberUser.accessToken).status shouldBe Created

`data in the Triples Store`(project, allCommitIds, memberUser.accessToken)

Then("the Status API should return OK with some status info")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import cats.syntax.all._
import io.renku.cli.model.CliProject
import io.renku.generators.Generators.Implicits._
import io.renku.graph.model.RenkuTinyTypeGenerators._
import io.renku.graph.model.testentities.generators.EntitiesGenerators.replaceProjectCreator
import io.renku.graph.model._
import io.renku.graph.model.gitlab.GitLabMember
import io.renku.graph.model.projects.Role
import io.renku.graph.model.testentities.generators.EntitiesGenerators.replaceProjectCreator
import io.renku.jsonld.JsonLD
import io.renku.jsonld.syntax._

Expand All @@ -39,18 +39,26 @@ trait ProjectFunctions {

def addMemberWithId(gitLabId: persons.GitLabId, role: Role): Project => Project =
p =>
p.copy(members =
p.members :+ GitLabMember(
personNames.generateOne,
personUsernames.generateOne,
gitLabId,
None,
Role.toGitLabAccessLevel(role)
)
p.copy(
members =
if (p.members.exists(_.user.gitLabId == gitLabId)) p.members
else
p.members :+ GitLabMember(
personNames.generateOne,
personUsernames.generateOne,
gitLabId,
None,
Role.toGitLabAccessLevel(role)
)
)

def addMemberFrom(person: testentities.Person, gitLabId: persons.GitLabId, role: Role): Project => Project =
p => p.copy(members = p.members :+ toProjectMember(person, gitLabId, role))
p =>
p.copy(
members =
if (p.members.exists(_.user.gitLabId == gitLabId)) p.members
else p.members :+ toProjectMember(person, gitLabId, role)
)

def toPayloadJsonLD(p: Project)(implicit renkuUrl: RenkuUrl): JsonLD =
toPayloadJsonLD(p.entitiesProject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ trait TSProvisioning
val ids = expect.map(_._1).toSet

implicit val showTuple: Show[(EventId, EventStatus)] =
Show.show { case (id, status) => s"$id:$status" }
Show.show { case (id, status) => s"${id.value.take(7)}:$status" }

implicit val showTuples: Show[Iterable[(EventId, EventStatus)]] =
Show.show(_.toList.mkString_(", "))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ final class GitLabApiStub[F[_]: Async: Logger](private val stateRef: Ref[F, Stat
case Some(AuthedUser(userId, _)) =>
if (id == userId) query(projectsFor(id.some)).flatMap(OkWithTotalHeader(req))
else OkWithTotalHeader(req)(List.empty[Project])
case Some(AuthedProject(projectId, _)) =>
case Some(AuthedProject(projectId, _, _)) =>
query(findProjectById(projectId)).map(_.toList).flatMap(OkWithTotalHeader(req))
case None =>
query(projectsFor(id.some)).flatMap(OkWithTotalHeader(req))
Expand Down Expand Up @@ -141,6 +141,7 @@ final class GitLabApiStub[F[_]: Async: Logger](private val stateRef: Ref[F, Stat
EitherT(req.as[Json].map(_.hcursor.downField("expires_at").as[LocalDate]))
.map(expiryDate => projectAccessTokenInfos.generateOne.copy(expiryDate = expiryDate))
.semiflatTap(tokenInfo => update(addProjectAccessToken(projectId, tokenInfo)))
.semiflatTap(tokenInfo => update(addPatAsProjectMember(projectId, tokenInfo)))
.semiflatMap(tokenInfo => Created().map(_.withEntity(tokenInfo.asJson)))
.leftSemiflatMap(err => BadRequest(s"No or invalid Project Access Token creation payload: ${err.message}"))
.merge
Expand All @@ -157,8 +158,9 @@ final class GitLabApiStub[F[_]: Async: Logger](private val stateRef: Ref[F, Stat
case GET -> Root / ProjectId(id) / "hooks" =>
query(findWebhooks(id)).flatMap(Ok(_))

case POST -> Root / ProjectId(_) / "hooks" =>
Created()
case POST -> Root / ProjectId(projectId) / "hooks" =>
update(addWebhook(projectId, GitLabStubIOSyntax.webhookUri)) >>
Created()

case GET -> Root / ProjectId(id) / "events" :? PageParam(page) :? ActionParam(action) =>
// action is always "pushed", page is always 1
Expand Down Expand Up @@ -221,6 +223,7 @@ final class GitLabApiStub[F[_]: Async: Logger](private val stateRef: Ref[F, Stat
}

object GitLabApiStub {

def apply[F[_]: Async: Logger](initial: State): F[GitLabApiStub[F]] =
Ref.of[F, State](initial).map(new GitLabApiStub[F](_))

Expand Down Expand Up @@ -254,5 +257,10 @@ object GitLabApiStub {
message: String,
parents: List[CommitId]
)
final case class ProjectAccessTokenInfo(tokenId: Int, name: String, token: ProjectAccessToken, expiryDate: LocalDate)
final case class ProjectAccessTokenInfo(tokenId: Int,
userId: persons.GitLabId,
name: String,
token: ProjectAccessToken,
expiryDate: LocalDate
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ private[gitlab] object GitLabAuth {
final case class AuthedUser(userId: persons.GitLabId, accessToken: UserAccessToken) extends AuthedReq {
type AT = UserAccessToken
}
final case class AuthedProject(projectId: projects.GitLabId, accessToken: ProjectAccessToken) extends AuthedReq {
final case class AuthedProject(projectId: projects.GitLabId,
userId: persons.GitLabId,
accessToken: ProjectAccessToken
) extends AuthedReq {
type AT = ProjectAccessToken
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ trait GitLabStateGenerators {

def projectAccessTokenInfos: Gen[ProjectAccessTokenInfo] = for {
id <- positiveInts()
userId <- GraphModelGenerators.personGitLabIds
token <- projectAccessTokens
expiry <- localDates(min = LocalDate.now().plusWeeks(1))
} yield ProjectAccessTokenInfo(
id.value,
userId,
name = find[Try, String]("project-token-name", ConfigFactory.load).fold(throw _, identity),
token,
expiry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ trait GitLabStateQueries {

def findAuthedProject(token: ProjectAccessToken): StateQuery[Option[AuthedProject]] =
_.projectAccessTokens.find(_._2.token == token).map { case (projectId, tokenInfo) =>
AuthedProject(projectId, tokenInfo.token)
AuthedProject(projectId, tokenInfo.userId, tokenInfo.token)
}

def findAuthedUser(token: UserAccessToken): StateQuery[Option[AuthedUser]] =
Expand All @@ -102,9 +102,9 @@ trait GitLabStateQueries {
}

def findCallerProjects: Option[AuthedReq] => StateQuery[List[Project]] = {
case None => _ => Nil
case Some(AuthedProject(_, _)) => _ => Nil
case Some(AuthedUser(userId, _)) => projectsWhereUserIsMember(userId)
case None => _ => Nil
case Some(AuthedProject(_, _, _)) => _ => Nil
case Some(AuthedUser(userId, _)) => projectsWhereUserIsMember(userId)
}

def findProject(id: projects.GitLabId, user: Option[persons.GitLabId]): StateQuery[Option[Project]] =
Expand All @@ -124,20 +124,20 @@ trait GitLabStateQueries {

def findProjectById(id: projects.GitLabId, maybeAuthedReq: Option[AuthedReq]): StateQuery[Option[Project]] =
maybeAuthedReq match {
case Some(AuthedProject(`id`, _)) => findProjectById(id)
case Some(AuthedProject(_, _)) => _ => None
case Some(AuthedUser(userId, _)) => findProject(id, userId.some)
case None => findProject(id, None)
case Some(AuthedProject(`id`, _, _)) => findProjectById(id)
case Some(AuthedProject(_, _, _)) => _ => None
case Some(AuthedUser(userId, _)) => findProject(id, userId.some)
case None => findProject(id, None)
}

def findProjectBySlug(slug: projects.Slug): StateQuery[Option[Project]] =
_.projects.find(_.slug == slug)

def findProjectBySlug(slug: projects.Slug, maybeAuthedReq: Option[AuthedReq]): StateQuery[Option[Project]] =
maybeAuthedReq match {
case Some(AuthedProject(id, _)) => findProject(id, slug)
case Some(AuthedUser(userId, _)) => findProject(slug, userId.some)
case None => findProject(slug, None)
case Some(AuthedProject(id, _, _)) => findProject(id, slug)
case Some(AuthedUser(userId, _)) => findProject(slug, userId.some)
case None => findProject(slug, None)
}

def findWebhooks(projectId: projects.GitLabId): StateQuery[List[Webhook]] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ package io.renku.graph.acceptancetests.stubs.gitlab
import GitLabApiStub._
import GitLabStateGenerators._
import cats.Monoid
import cats.syntax.all._
import cats.data.NonEmptyList
import cats.syntax.all._
import io.renku.generators.Generators.Implicits._
import io.renku.graph.acceptancetests.data.Project
import io.renku.graph.acceptancetests.data.{Project, ProjectFunctions}
import io.renku.graph.model._
import io.renku.graph.model.entities.EntityFunctions
import io.renku.graph.model.events.CommitId
import io.renku.graph.model.testentities.{Person, Project => RenkuProject}
import io.renku.graph.model._
import io.renku.graph.model.gitlab.GitLabUser
import io.renku.graph.model.testentities.{Person, Project => RenkuProject}
import io.renku.http.client.UserAccessToken
import monocle.Traversal
import org.http4s.Uri

/** Collection of functions to update the state in [[GitLabApiStub]]. */
Expand All @@ -48,6 +49,8 @@ trait GitLabStateUpdates {
def clearState: StateUpdate =
_ => State.empty

private val projectsLens = Traversal.fromTraverse[List, Project]

def addUser(id: persons.GitLabId, token: UserAccessToken): StateUpdate =
state => state.copy(users = state.users.updated(id, token))

Expand Down Expand Up @@ -97,10 +100,12 @@ trait GitLabStateUpdates {
state.copy(persons = glIdPersons.toList ::: state.persons.filterNot(p => p.maybeGitLabId.exists(ids.contains)))
}

def addProject(project: Project): StateUpdate =
state => state.copy(projects = project :: state.projects.filter(_.id != project.id))
def addProject(project: Project)(implicit renkuUrl: RenkuUrl): StateUpdate =
((state: State) => state.copy(projects = project :: state.projects.filter(_.id != project.id))) >>
addPersons(EntityFunctions[RenkuProject].findAllPersons(project.entitiesProject).map(toPerson)) >>
addPersons((project.members.map(_.user) appendList project.maybeCreator.toList).map(userToPerson).toList)

def addProject(project: Project, webhook: Uri): StateUpdate =
def addProject(project: Project, webhook: Uri)(implicit renkuUrl: RenkuUrl): StateUpdate =
addProject(project) >> addWebhook(project.id, webhook)

def setupProject(project: Project, webhook: Uri, commits: CommitId*)(implicit renkuUrl: RenkuUrl): StateUpdate =
Expand All @@ -112,6 +117,16 @@ trait GitLabStateUpdates {
def addProjectAccessToken(projectId: projects.GitLabId, token: ProjectAccessTokenInfo): StateUpdate =
state => state.copy(projectAccessTokens = state.projectAccessTokens.updated(projectId, token))

def addPatAsProjectMember(projectId: projects.GitLabId, token: ProjectAccessTokenInfo): StateUpdate = {
val patPerson = testentities.Person(persons.Name("renku"), maybeGitLabId = Some(token.userId))
state =>
state.copy(projects = projectsLens.modify {
case p if p.id == projectId =>
ProjectFunctions.addMemberFrom(patPerson, token.userId, projects.Role.Maintainer)(p)
case p => p
}(state.projects))
}

private lazy val toPerson: entities.Person => Person = person =>
Person(
person.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ import io.renku.testtools.IOSpec
import org.http4s.Uri

/** Convenience syntax for test cases to update the [[GitLabApiStub]] state. */
trait GitLabStubIOSyntax { self: IOSpec =>
object GitLabStubIOSyntax {
val webhookUri: Uri = Uri.unsafeFromString("http://localhost:9001/webhooks/events")
}

trait GitLabStubIOSyntax { self: IOSpec =>

import GitLabStubIOSyntax.webhookUri

final implicit class StubOps(self: GitLabApiStub[IO]) {

Expand All @@ -52,7 +57,7 @@ trait GitLabStubIOSyntax { self: IOSpec =>
/** Adds a gitlab project. The project will be available, but no integration hooks are created. See
* `setupProject`.
*/
def addProject(project: Project): Unit =
def addProject(project: Project)(implicit renkuUrl: RenkuUrl): Unit =
self.update(GitLabStateUpdates.addProject(project)).unsafeRunSync()

/** Adds a webhook to a gitlab project. The assumption is the project is already added to GitLab
Expand All @@ -67,7 +72,7 @@ trait GitLabStubIOSyntax { self: IOSpec =>
self.update(GitLabStateUpdates.setupProject(project, webhookUri, commits: _*)).unsafeRunSync()

/** Adds the given project and removes any existing project with the same id. */
def replaceProject(project: Project): Unit =
def replaceProject(project: Project)(implicit renkuUrl: RenkuUrl): Unit =
addProject(project)

/** Removes all existing commits of the project with `id` and associates the given commits. */
Expand Down
Loading

0 comments on commit 7dcab35

Please sign in to comment.