diff options
30 files changed, 407 insertions, 139 deletions
diff --git a/app/finders/ci/catalog/resources/versions_finder.rb b/app/finders/ci/catalog/resources/versions_finder.rb index b37d4f0377a..16f8531c5c4 100644 --- a/app/finders/ci/catalog/resources/versions_finder.rb +++ b/app/finders/ci/catalog/resources/versions_finder.rb @@ -18,6 +18,7 @@ module Ci versions = params[:latest] ? get_latest_versions : get_versions versions = versions.preloaded + versions = by_name(versions) sort(versions) end @@ -45,6 +46,12 @@ module Ci end strong_memoize_attr :authorized_catalog_resources + def by_name(versions) + return versions unless params[:name] + + versions.by_name(params[:name]) + end + def sort(versions) versions.order_by(params[:sort] || DEFAULT_SORT) end diff --git a/app/graphql/resolvers/ci/catalog/resources/versions_resolver.rb b/app/graphql/resolvers/ci/catalog/resources/versions_resolver.rb index 9332076a493..899b407b180 100644 --- a/app/graphql/resolvers/ci/catalog/resources/versions_resolver.rb +++ b/app/graphql/resolvers/ci/catalog/resources/versions_resolver.rb @@ -11,12 +11,18 @@ module Resolvers # field is evaluated on more than one node, it causes performance degradation. extension ::Gitlab::Graphql::Limit::FieldCallCount, limit: 1 + argument :name, GraphQL::Types::String, + required: false, + description: 'Name of the version.' + argument :sort, Types::Ci::Catalog::Resources::VersionSortEnum, required: false, description: 'Sort versions by given criteria.' - def resolve(sort: nil) - ::Ci::Catalog::Resources::VersionsFinder.new(object, current_user, sort: sort).execute + alias_method :catalog_resource, :object + + def resolve(name: nil, sort: nil) + ::Ci::Catalog::Resources::VersionsFinder.new(catalog_resource, current_user, name: name, sort: sort).execute end end end diff --git a/app/graphql/types/ci/catalog/resources/version_type.rb b/app/graphql/types/ci/catalog/resources/version_type.rb index 87876b74f77..c568403f320 100644 --- a/app/graphql/types/ci/catalog/resources/version_type.rb +++ b/app/graphql/types/ci/catalog/resources/version_type.rb @@ -47,9 +47,23 @@ module Types description: 'Components belonging to the catalog resource.', alpha: { milestone: '16.7' } + field :readme_html, GraphQL::Types::String, null: true, calls_gitaly: true, + description: 'GitLab Flavored Markdown rendering of README.md. This field ' \ + 'can only be resolved for one version in any single request.', + alpha: { milestone: '16.8' } do + extension ::Gitlab::Graphql::Limit::FieldCallCount, limit: 1 # To avoid N+1 calls to Gitaly + end + def author Gitlab::Graphql::Loaders::BatchModelLoader.new(User, object.author_id).find end + + def readme_html + return unless Ability.allowed?(current_user, :read_code, object.project) + + markdown_context = context.to_h.dup.merge(project: object.project) + ::MarkupHelper.markdown(object.readme&.data, markdown_context) + end end # rubocop: enable Graphql/AuthorizeTypes end diff --git a/app/models/ci/catalog/resources/version.rb b/app/models/ci/catalog/resources/version.rb index e3d3ac7b513..0ea2735b030 100644 --- a/app/models/ci/catalog/resources/version.rb +++ b/app/models/ci/catalog/resources/version.rb @@ -19,6 +19,7 @@ module Ci scope :for_catalog_resources, ->(catalog_resources) { where(catalog_resource_id: catalog_resources) } scope :preloaded, -> { includes(:catalog_resource, project: [:route, { namespace: :route }], release: :author) } + scope :by_name, ->(name) { joins(:release).merge(Release.where(tag: name)) } scope :order_by_created_at_asc, -> { reorder(created_at: :asc) } scope :order_by_created_at_desc, -> { reorder(created_at: :desc) } @@ -126,6 +127,10 @@ module Ci Gitlab::Routing.url_helpers.project_tag_path(project, name) end + def readme + project.repository.tree(sha).readme + end + private def update_catalog_resource diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 6669ed071e0..a7e6409b8aa 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -15550,6 +15550,7 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="cicatalogresourceversionsname"></a>`name` | [`String`](#string) | Name of the version. | | <a id="cicatalogresourceversionssort"></a>`sort` | [`CiCatalogResourceVersionSort`](#cicatalogresourceversionsort) | Sort versions by given criteria. | ### `CiCatalogResourceComponent` @@ -15586,6 +15587,7 @@ four standard [pagination arguments](#connection-pagination-arguments): | <a id="cicatalogresourceversionid"></a>`id` **{warning-solid}** | [`CiCatalogResourcesVersionID!`](#cicatalogresourcesversionid) | **Introduced** in 16.7. This feature is an Experiment. It can be changed or removed at any time. Global ID of the version. | | <a id="cicatalogresourceversionname"></a>`name` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.8. This feature is an Experiment. It can be changed or removed at any time. Name that uniquely identifies the version within the catalog resource. | | <a id="cicatalogresourceversionpath"></a>`path` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.8. This feature is an Experiment. It can be changed or removed at any time. Relative web path to the version. | +| <a id="cicatalogresourceversionreadmehtml"></a>`readmeHtml` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.8. This feature is an Experiment. It can be changed or removed at any time. GitLab Flavored Markdown rendering of README.md. This field can only be resolved for one version in any single request. | | <a id="cicatalogresourceversionreleasedat"></a>`releasedAt` **{warning-solid}** | [`Time`](#time) | **Introduced** in 16.7. This feature is an Experiment. It can be changed or removed at any time. Timestamp of when the version was released. | | <a id="cicatalogresourceversiontagname"></a>`tagName` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.7. This feature is an Experiment. It can be changed or removed at any time. Deprecated in 16.8. Use name. | | <a id="cicatalogresourceversiontagpath"></a>`tagPath` **{warning-solid}** | [`String`](#string) | **Introduced** in 16.7. This feature is an Experiment. It can be changed or removed at any time. Deprecated in 16.8. Use path. | diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md index 4a6e0118f3b..bc79ff0ad7a 100644 --- a/doc/ci/environments/index.md +++ b/doc/ci/environments/index.md @@ -24,7 +24,7 @@ associated with your project, you can use it to assist with your deployments. Prerequisites: -- You must have at least the Reporter role. +- In a private project, you must have at least the Reporter role. See [Environment permissions](#environment-permissions). There are a few ways to view a list of environments for a given project: @@ -912,6 +912,38 @@ like [Review Apps](../review_apps/index.md) (`review/*`). The most specific spec takes precedence over the other wildcard matching. In this case, the `review/feature-1` spec takes precedence over `review/*` and `*` specs. +## Environment permissions + +Depending on your role, you can interact with environments in public +and private projects. + +### View environments + +- In public projects, anyone can view a list of environments, including non-members. +- In private projects, you must have at least the Reporter role to view a list of environments. + +### Create and update environments + +- You must have at least the Developer role to create a new environment, or update an existing unprotected environment. +- If an existing environment is protected and you don't have access to it, you cannot update the environment. + +### Stop and delete environments + +- You must have at least the Developer role to stop or delete an unprotected environment. +- If an environment is protected and you don't have access to it, you cannot stop or delete the environment. + +### Run deployment jobs in protected environments + +If you can push or merge to the protected branch: + +- You must have at least the Reporter role. + +If you can't push to the protected branch: + +- You must be a part of a group with the Reporter role. + +See [Deployment-only access to protected environments](protected_environments.md#deployment-only-access-to-protected-environments). + ## Related topics - [Dashboard for Kubernetes](kubernetes_dashboard.md) diff --git a/doc/ci/pipelines/cicd_minutes.md b/doc/ci/pipelines/cicd_minutes.md index 699136ccf97..e555b3faa00 100644 --- a/doc/ci/pipelines/cicd_minutes.md +++ b/doc/ci/pipelines/cicd_minutes.md @@ -1,6 +1,7 @@ --- stage: Verify group: Pipeline Execution +description: Calculations, quotas, purchase information. info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/solutions/cloud/aws/gitlab_aws_integration.md b/doc/solutions/cloud/aws/gitlab_aws_integration.md index 11add88f7c0..31459fca747 100644 --- a/doc/solutions/cloud/aws/gitlab_aws_integration.md +++ b/doc/solutions/cloud/aws/gitlab_aws_integration.md @@ -15,19 +15,15 @@ When content that is badged for GitLab SaaS ( **(SAAS)** ) or Self-Managed ( **( This page attempts to index the ways in which GitLab can integrate with AWS. It does so whether the integration is the result of configuring general functionality, was built in to AWS or GitLab or is provided as a solution. -| Text Tag | Configuration / Built / Solution | Support/Maintenance | -| -------------------- | ------------------------------------------------------------ | ------------------- | -| `[AWS Configuration]` | Integration via Configuring Existing AWS Functionality | AWS | -| `[GitLab Configuration]` | Integration via Configuring Existing GitLab Functionality | GitLab | -| `[AWS Built]` | Built into AWS by Product Team to Address AWS Integration | AWS | -| `[GitLab Built]` | Built into GitLab by Product Team to Address AWS Integration | GitLab | -| `[AWS Solution]` | Built as Solution Example by AWS or AWS Partners | Community/Example | -| `[GitLab Solution]` | Built as Solution Example by GitLab or GitLab Partners | Community/Example | -| `[CI Solution]` | Built, at least in part, using GitLab CI and therefore <br />more customer customizable. | Items tagged `[CI Solution]` will <br />also carry one of the other tags <br />that indicate the maintenance status. | - -## Table of Contents - -[TOC] +| Text Tag | Configuration / Built / Solution | Support/Maintenance | +| ------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| `[AWS Configuration]` | Integration via Configuring Existing AWS Functionality | AWS | +| `[GitLab Configuration]` | Integration via Configuring Existing GitLab Functionality | GitLab | +| `[AWS Built]` | Built into AWS by Product Team to Address AWS Integration | AWS | +| `[GitLab Built]` | Built into GitLab by Product Team to Address AWS Integration | GitLab | +| `[AWS Solution]` | Built as Solution Example by AWS or AWS Partners | Community/Example | +| `[GitLab Solution]` | Built as Solution Example by GitLab or GitLab Partners | Community/Example | +| `[CI Solution]` | Built, at least in part, using GitLab CI and therefore <br />more customer customizable. | Items tagged `[CI Solution]` will <br />also carry one of the other tags <br />that indicate the maintenance status. | ## Integrations For Development Activities @@ -35,47 +31,90 @@ These integrations have to do with using GitLab to build application workloads a ### SCM Integrations -- **AWS CodeStar Connections** - enables SCM connections to multiple AWS Services. **Currently for GitLab.com SaaS only**. [Configure GitLab](https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-gitlab.html). [Supported Providers](https://docs.aws.amazon.com/dtconsole/latest/userguide/supported-versions-connections.html). [Supported AWS Services](https://docs.aws.amazon.com/dtconsole/latest/userguide/integrations-connections.html) - each one may have to make updates to support GitLab, so here is the subset that currently support GitLab `[AWS Built]` - - [AWS CodePipeline Integration](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab.html) - use GitLab as source for CodePipeline. `[AWS Built]` - - **AWS CodeBuild Integration** - indirectly through CodePipeline support. `[AWS Built]` - - **Amazon CodeWhisperer Customization Capability** [can connect to a GitLab repo](https://aws.amazon.com/blogs/aws/new-customization-capability-in-amazon-codewhisperer-generates-even-better-suggestions-preview/). `[AWS Built]` - - **AWS Service Catalog** directly inherits CodeStar Connections, there is not any specific documentation about GitLab since it just uses any GitLab CodeStar Connection that has been created in the account. `[AWS Built]` - - **AWS Proton** directly inherits CodeStar Connections, there is not any specific documentation about GitLab since it just uses any GitLab CodeStar Connection that has been created in the account. `[AWS Built]` - - **AWS Glue Notebook Jobs** directly inherit CodeStar Connections, there is not any specific documentation about GitLab since it just uses any GitLab CodeStar Connection that has been created in the account. `[AWS Built]` - - **Amazon SageMaker MLOps Projects** are done in CodePipeline and so directly inherit CodeStar Connections ([as noted here](https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-projects-walkthrough-3rdgit.html#sagemaker-proejcts-walkthrough-connect-3rdgit)), there is not any specific documentation about GitLab since it just uses any GitLab CodeStar Connection that has been created in the account. `[AWS Built]` - - **Amazon SageMaker Notebooks** [allow Git repositories to be specified by the Git clone URL](https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-git-resource.html) and configuration of a secret - so GitLab is configurable. `[AWS Configuration]` - - **AWS CloudFormation** publishing of public extensions - **not yet supported**. `[AWS Built]` - - **Amazon CodeGuru Reviewer Repositories** - **not yet supported**. `[AWS Built]` -- [GitLab Push Mirroring to CodeCommit](../../../user/project/repository/mirror/push.md#set-up-a-push-mirror-from-gitlab-to-aws-codecommit) Workaround enables GitLab repositories to leverage CodePipeline SCM Triggers. GitLab can already leverage S3 and Container Triggers for CodePipeline. **Still required for Self-Managed and Dedicated for the time being.** `[GitLab Configuration]` +#### AWS CodeStar Connection Integrations + +[8/14/2023 AWS Release Announcement for GitLab.com SaaS](https://aws.amazon.com/about-aws/whats-new/2023/08/aws-codepipeline-supports-gitlab/) + +[12/28/2023 AWS Release Announcement for Self-Managed / Dedicated](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/) + +**AWS CodeStar Connections** - enables SCM connections to multiple AWS Services. [Configure GitLab](https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-gitlab.html). [Supported Providers](https://docs.aws.amazon.com/dtconsole/latest/userguide/supported-versions-connections.html). [Supported AWS Services](https://docs.aws.amazon.com/dtconsole/latest/userguide/integrations-connections.html) - each one may have to make updates to support GitLab, so here is the subset that support GitLab. This works with GitLab.com SaaS, GitLab Self-Managed and GitLab Dedicated. AWS CodeStar connections are not available in all AWS regions - the exclusion list is [documented here](https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodestarConnectionSource.html). [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Built]` + +[Video Explanation of AWS CodeStar Connection Integration for AWS (1 min)](https://youtu.be/f7qTSa_bNig) + +AWS Services that are supported directly by a CodeStar Connection in an AWS account: + +- **Amazon CodeWhisperer Customization Capability** [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] [can connect to a GitLab repository](https://aws.amazon.com/blogs/aws/new-customization-capability-in-amazon-codewhisperer-generates-even-better-suggestions-preview/). `[AWS Built]` +- **AWS Service Catalog** directly inherits CodeStar Connections, there is not any specific documentation about GitLab because it just uses any GitLab CodeStar Connection that has been created in the account. [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Built]` +- **AWS Proton** directly inherits CodeStar Connections, there is not any specific documentation about GitLab since it just uses any GitLab CodeStar Connection that has been created in the account. [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Built]` +- **AWS Glue Notebook Jobs** directly inherit CodeStar Connections, there is not any specific documentation about GitLab because it just uses any GitLab CodeStar Connection that has been created in the account. [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Built]` + +Documentation and References: + +- [Creating a GitLab CodeStar Connection to a GitLab.com Project](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab-managed.html) +- [Creating a AWS CodeStar Connection for a Self-Managed GitLab Instance or GitLab Dedicated Instance](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab-managed.html) (must allow Internet Ingress from AWS or use a VPC connection) + +#### AWS CodePipeline Integrations + +[AWS CodePipeline Integration](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab.html) - by using GitLab as CodeStar Connections source for CodePipeline, additional AWS service integrations are available. [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Built]` + +AWS Services that are supported by an AWS CodePipeline integration: + +- **AWS CodeBuild Integration** - through CodePipeline support. [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Built]` +- **Amazon SageMaker MLOps Projects** are created via CodePipeline ([as noted here](https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-projects-walkthrough-3rdgit.html#sagemaker-proejcts-walkthrough-connect-3rdgit)), there is not any specific documentation about GitLab since it just uses any GitLab CodeStar Connection that has been created in the account. [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Built]` + +Documentation and References: + +- [Creating a GitLab CodePipeline Integration to a GitLab.com Project](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab-managed.html) +- [Creating a AWS CodePipeline Integration for a Self-Managed GitLab Instance or GitLab Dedicated Instance](https://docs.aws.amazon.com/codepipeline/latest/userguide/connections-gitlab-managed.html) (must allow Internet Ingress from AWS or use a VPC connection) + +#### CodeStar Connections enabled AWS services that are not yet supported for GitLab + +- **AWS CloudFormation** publishing of public extensions - not yet supported. `[AWS Built]` +- **Amazon CodeGuru Reviewer Repositories** - not yet supported. `[AWS Built]` +- **AWS App Runner** - not yet supported. `[AWS Built]` + +#### Custom GitLab Integration in AWS Services + +- **Amazon SageMaker Notebooks** [allow Git repositories to be specified by the Git clone URL](https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-git-resource.html) and configuration of a secret - so GitLab is configurable. [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Configuration]` +- **AWS Amplify** - [uses a Git integration mechanism designed by the AWS Amplify team](https://docs.aws.amazon.com/amplify/latest/userguide/getting-started.html). `[AWS Built]` + +#### Other SCM Integration Options + +- [GitLab Push Mirroring to CodeCommit](../../../user/project/repository/mirror/push.md#set-up-a-push-mirror-from-gitlab-to-aws-codecommit) Workaround enables GitLab repositories to leverage CodePipeline SCM Triggers. GitLab can already leverage S3 and Container Triggers for CodePipeline. This work around enabled CodePipeline capabilities since it was documented. [06/06/2020] `[GitLab Configuration]` + +See [CD and Operations Integrations](#cd-and-operations-integrations) below for Continuous Deployment (CD) specific integrations that are also available. ### CI Integrations - **Direct CI Integrations That Use Keys, IAM or OIDC/JWT to Authenticate to AWS Services from GitLab Runners** - - **Amazon CodeGuru Reviewer CI workflows using GitLab CI** - can be done, not yet documented. `[AWS Solution]` `[CI Solution]` - - [Amazon CodeGuru Secure Scanning using GitLab CI](https://docs.aws.amazon.com/codeguru/latest/security-ug/get-started-gitlab.html) `[AWS Solution]` `[CI Solution]` +- **Amazon CodeGuru Reviewer CI workflows using GitLab CI** - can be done, not yet documented.`[AWS Solution]` `[CI Solution]` +- [Amazon CodeGuru Secure Scanning using GitLab CI](https://docs.aws.amazon.com/codeguru/latest/security-ug/get-started-gitlab.html) [[06/13/2022](https://aws.amazon.com/about-aws/whats-new/2023/06/amazon-codeguru-security-available-preview/)] `[AWS Solution]` `[CI Solution]` ### CD and Operations Integrations -- **AWS CodeDeploy Integration** - indirectly through CodePipeline support. `[AWS Built]` +- **AWS CodeDeploy Integration** - through CodePipeline support dicussed above in SCM integrations. This capability allows GitLab to interface with [this list of advanced deployment subsystems in AWS](https://docs.aws.amazon.com/codepipeline/latest/userguide/integrations-action-type.html#integrations-deploy). [[12/28/2023](https://aws.amazon.com/about-aws/whats-new/2023/12/codepipeline-gitlab-self-managed/)] `[AWS Built]` +- **AWS SAM Pipelines** - [pipelines support for GitLab](https://aws.amazon.com/about-aws/whats-new/2021/07/simplify-ci-cd-configuration-serverless-applications-your-favorite-ci-cd-system-public-preview). [7/31/2021] - [Integrate EKS clusters for application deployment](../../../user/infrastructure/clusters/connect/new_eks_cluster.md). `[GitLab Built]` +- [GitLab pushing a build Artifact to a CodePipeline monitored S3 location](https://docs.aws.amazon.com/codepipeline/latest/userguide/pipelines-about-starting.html#change-detection-methods) `[AWS Built]` +- [GitLab Pushing a container to a CodePipeline monitored AWS ECR](https://docs.aws.amazon.com/codepipeline/latest/userguide/pipelines-about-starting.html#change-detection-methods) `[AWS Built]` -## End-to-End Solutions for development and deployment if specific development frameworks and ecosystems +## End-to-End Solutions for development and deployment of specific development frameworks or ecosystems Generally solutions demonstrate end-to-end capabilities for the development framework - leveraging all relevant integration techniques to show the art of maximum value for using GitLab and AWS together. ### Serverless -- [Serverless Framework Deployment to AWS with GitLab Serverless SAST Scanning and Lifecycle Managed DevOps Environments](https://gitlab.com/guided-explorations/aws/serverless/serverless-framework-aws) - working example code and tutorials. `[GitLab Solution]` `[CI Solution]` +- [Enterprise DevOps Blueprint: Serverless Framework Apps on AWS](https://gitlab.com/guided-explorations/aws/serverless/serverless-framework-aws) - working example code and tutorials. `[GitLab Solution]` `[CI Solution]` - [Tutorial: Serverless Framework Deployment to AWS with GitLab Serverless SAST Scanning](https://gitlab.com/guided-explorations/aws/serverless/serverless-framework-aws/-/blob/master/TUTORIAL.md) `[GitLab Solution]` `[CI Solution]` - [Tutorial: Secure Serverless Framework Development with GitLab Security Policy Approval Rules and Managed DevOps Environments](https://gitlab.com/guided-explorations/aws/serverless/serverless-framework-aws/-/blob/master/TUTORIAL2-SecurityAndManagedEnvs.md) `[GitLab Solution]` `[CI Solution]` ### Terraform -- [Terraform Deployment to AWS with GitLab Lifecycle Managed DevOps Environments](https://gitlab.com/guided-explorations/aws/terraform/terraform-web-server-cluster) +- [Enterprise DevOps Blueprint: Terraform Deployment to AWS](https://gitlab.com/guided-explorations/aws/terraform/terraform-web-server-cluster) - [Tutorial: Terraform Deployment to AWS with GitLab IaC SAST Scanning](https://gitlab.com/guided-explorations/aws/terraform/terraform-web-server-cluster/-/blob/prod/TUTORIAL.md) `[GitLab Solution]` `[CI Solution]` - [Terraform Deployment to AWS with GitLab Security Policy Approval Rules and Managed DevOps Environments](https://gitlab.com/guided-explorations/aws/terraform/terraform-web-server-cluster/-/blob/prod/TUTORIAL2-SecurityAndManagedEnvs.md) `[GitLab Solution]` `[CI Solution]` -#### CloudFormation +### CloudFormation [CloudFormation Development and Deployment With GitLab Lifecycle Managed DevOps Environments Working Code](https://gitlab.com/guided-explorations/aws/cloudformation-deploy) `[GitLab Solution]` `[CI Solution]` diff --git a/doc/subscriptions/choosing_subscription.md b/doc/subscriptions/choosing_subscription.md index aa7ba3a9042..04e05ef1be9 100644 --- a/doc/subscriptions/choosing_subscription.md +++ b/doc/subscriptions/choosing_subscription.md @@ -1,6 +1,7 @@ --- stage: Fulfillment group: Purchase +description: Options for accessing GitLab. info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/subscriptions/community_programs.md b/doc/subscriptions/community_programs.md index 309a100de7a..a7b95c78491 100644 --- a/doc/subscriptions/community_programs.md +++ b/doc/subscriptions/community_programs.md @@ -1,6 +1,7 @@ --- stage: Fulfillment group: Purchase +description: Education, Open Source, Startups. info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/subscriptions/customers_portal.md b/doc/subscriptions/customers_portal.md index 0b57945f7fb..9b669460e80 100644 --- a/doc/subscriptions/customers_portal.md +++ b/doc/subscriptions/customers_portal.md @@ -1,6 +1,7 @@ --- stage: Fulfillment group: Purchase +description: Payment and company details. info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md index 910ba7bece7..76b6c59c9fe 100644 --- a/doc/subscriptions/gitlab_com/index.md +++ b/doc/subscriptions/gitlab_com/index.md @@ -1,6 +1,7 @@ --- stage: Fulfillment group: Purchase +description: Seat usage, compute minutes, storage limits, renewal info. info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/subscriptions/gitlab_dedicated/index.md b/doc/subscriptions/gitlab_dedicated/index.md index 4c4146a9798..0cf604f620f 100644 --- a/doc/subscriptions/gitlab_dedicated/index.md +++ b/doc/subscriptions/gitlab_dedicated/index.md @@ -1,6 +1,7 @@ --- stage: SaaS Platforms group: GitLab Dedicated +description: Available features and benefits. info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/subscriptions/quarterly_reconciliation.md b/doc/subscriptions/quarterly_reconciliation.md index 48b571322a1..db822a3569e 100644 --- a/doc/subscriptions/quarterly_reconciliation.md +++ b/doc/subscriptions/quarterly_reconciliation.md @@ -1,6 +1,7 @@ --- stage: Fulfillment group: Purchase +description: Billing examples. info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index b0510ba5910..9a232256de2 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -1,6 +1,7 @@ --- stage: Fulfillment group: Purchase +description: Billable users, renewal and upgrade info. info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/tutorials/build_application.md b/doc/tutorials/build_application.md index 9c10a755292..ea899ee107e 100644 --- a/doc/tutorials/build_application.md +++ b/doc/tutorials/build_application.md @@ -1,6 +1,7 @@ --- stage: none group: Tutorials +description: CI/CD fundamentals and examples. info: For assistance with this tutorials page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects. --- diff --git a/doc/tutorials/develop.md b/doc/tutorials/develop.md index bc0015b2d29..c893a4839d4 100644 --- a/doc/tutorials/develop.md +++ b/doc/tutorials/develop.md @@ -1,6 +1,7 @@ --- stage: none group: Tutorials +description: Integrations with third-party services. info: For assistance with this tutorials page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects. --- diff --git a/doc/tutorials/gitlab_navigation.md b/doc/tutorials/gitlab_navigation.md index 8b91d799f91..b456b0ee18f 100644 --- a/doc/tutorials/gitlab_navigation.md +++ b/doc/tutorials/gitlab_navigation.md @@ -1,6 +1,7 @@ --- stage: none group: Tutorials +description: Introduction to the product. info: For assistance with this tutorials page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects. --- diff --git a/doc/tutorials/infrastructure.md b/doc/tutorials/infrastructure.md index 49cd0e95230..0097d06e316 100644 --- a/doc/tutorials/infrastructure.md +++ b/doc/tutorials/infrastructure.md @@ -1,6 +1,7 @@ --- stage: none group: Tutorials +description: GitOps, Kubernetes deployments. info: For assistance with this tutorials page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects. --- diff --git a/doc/tutorials/learn_git.md b/doc/tutorials/learn_git.md index 2ebc1f3fd0e..a8333734982 100644 --- a/doc/tutorials/learn_git.md +++ b/doc/tutorials/learn_git.md @@ -1,6 +1,7 @@ --- stage: none group: Tutorials +description: Git basics. info: For assistance with this tutorials page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects. --- diff --git a/doc/tutorials/plan_and_track.md b/doc/tutorials/plan_and_track.md index b3ec1fb4755..f03aff933f6 100644 --- a/doc/tutorials/plan_and_track.md +++ b/doc/tutorials/plan_and_track.md @@ -1,6 +1,7 @@ --- stage: none group: Tutorials +description: Planning, agile, issue boards. info: For assistance with this tutorials page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects. --- diff --git a/doc/tutorials/secure_application.md b/doc/tutorials/secure_application.md index 4868ec53ed3..ac139a88cf1 100644 --- a/doc/tutorials/secure_application.md +++ b/doc/tutorials/secure_application.md @@ -1,6 +1,7 @@ --- stage: none group: Tutorials +description: Dependency and compliance scanning. info: For assistance with this tutorials page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments-to-other-projects-and-subjects. --- diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb index db60101ab14..651e2a4fc9c 100644 --- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb +++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb @@ -85,7 +85,7 @@ module QA # Imported objects # - let(:imported_project) { imported_group.projects(auto_paginate: true, attempts: 3).find { |project| project.name == gitlab_source_project }.reload! } + let(:imported_project) { imported_group.projects(auto_paginate: true).find { |project| project.name == gitlab_source_project }.reload! } let(:branches) { imported_project.repository_branches(auto_paginate: true, attempts: 3).map { |b| b[:name] } } let(:commits) { imported_project.commits(auto_paginate: true, attempts: 3).map { |c| c[:id] } } let(:labels) { imported_project.labels(auto_paginate: true, attempts: 3).map { |l| l.except(:id, :description_html) } } diff --git a/spec/finders/ci/catalog/resources/versions_finder_spec.rb b/spec/finders/ci/catalog/resources/versions_finder_spec.rb index b541b84f198..dbde77101ee 100644 --- a/spec/finders/ci/catalog/resources/versions_finder_spec.rb +++ b/spec/finders/ci/catalog/resources/versions_finder_spec.rb @@ -5,9 +5,10 @@ require 'spec_helper' RSpec.describe Ci::Catalog::Resources::VersionsFinder, feature_category: :pipeline_composition do include_context 'when there are catalog resources with versions' + let(:name) { nil } let(:sort) { nil } let(:latest) { nil } - let(:params) { { sort: sort, latest: latest }.compact } + let(:params) { { name: name, sort: sort, latest: latest }.compact } subject(:execute) { described_class.new([resource1, resource2], current_user, params).execute } @@ -18,7 +19,7 @@ RSpec.describe Ci::Catalog::Resources::VersionsFinder, feature_category: :pipeli new_user = create(:user) expect do - described_class.new([resource1, resource2, resource3], new_user, params).execute + described_class.new([resource1, resource2], new_user, params).execute end.not_to exceed_query_limit(control_count) end @@ -37,6 +38,23 @@ RSpec.describe Ci::Catalog::Resources::VersionsFinder, feature_category: :pipeli expect(execute).to match_array([v1_0, v1_1]) end + context 'with name parameter' do + let(:name) { 'v1.0' } + + it 'returns the version that matches the name' do + expect(execute.count).to eq(1) + expect(execute.first.name).to eq('v1.0') + end + + context 'when no version matches the name' do + let(:name) { 'does_not_exist' } + + it 'returns empty response' do + is_expected.to be_empty + end + end + end + context 'with sort parameter' do it 'returns versions ordered by released_at descending by default' do expect(execute).to eq([v1_1, v1_0]) diff --git a/spec/graphql/resolvers/ci/catalog/resources/versions_resolver_spec.rb b/spec/graphql/resolvers/ci/catalog/resources/versions_resolver_spec.rb index 1ce0e91765f..4205259e5b9 100644 --- a/spec/graphql/resolvers/ci/catalog/resources/versions_resolver_spec.rb +++ b/spec/graphql/resolvers/ci/catalog/resources/versions_resolver_spec.rb @@ -7,8 +7,9 @@ RSpec.describe Resolvers::Ci::Catalog::Resources::VersionsResolver, feature_cate include_context 'when there are catalog resources with versions' + let(:name) { nil } let(:sort) { nil } - let(:args) { { sort: sort }.compact } + let(:args) { { name: name, sort: sort }.compact } let(:ctx) { { current_user: current_user } } subject(:result) { resolve(described_class, ctx: ctx, obj: resource1, args: args) } @@ -19,6 +20,23 @@ RSpec.describe Resolvers::Ci::Catalog::Resources::VersionsResolver, feature_cate resource1.project.add_guest(current_user) end + context 'when name argument is provided' do + let(:name) { 'v1.0' } + + it 'returns the version that matches the name' do + expect(result.items.size).to eq(1) + expect(result.items.first.name).to eq('v1.0') + end + + context 'when no version matches the name' do + let(:name) { 'does_not_exist' } + + it 'returns empty response' do + expect(result).to be_empty + end + end + end + context 'when sort argument is not provided' do it 'returns versions ordered by released_at descending' do expect(result.items).to eq([v1_1, v1_0]) diff --git a/spec/graphql/types/ci/catalog/resources/version_type_spec.rb b/spec/graphql/types/ci/catalog/resources/version_type_spec.rb index e218be57819..10eea90e949 100644 --- a/spec/graphql/types/ci/catalog/resources/version_type_spec.rb +++ b/spec/graphql/types/ci/catalog/resources/version_type_spec.rb @@ -17,6 +17,7 @@ RSpec.describe Types::Ci::Catalog::Resources::VersionType, feature_category: :pi author commit components + readme_html ] expect(described_class).to have_graphql_fields(*expected_fields) diff --git a/spec/models/ci/catalog/resources/version_spec.rb b/spec/models/ci/catalog/resources/version_spec.rb index aafd51699b5..bacaa6355fe 100644 --- a/spec/models/ci/catalog/resources/version_spec.rb +++ b/spec/models/ci/catalog/resources/version_spec.rb @@ -28,6 +28,23 @@ RSpec.describe Ci::Catalog::Resources::Version, type: :model, feature_category: end end + describe '.by_name' do + it 'returns the version that matches the name' do + versions = described_class.by_name('v1.0') + + expect(versions.count).to eq(1) + expect(versions.first.name).to eq('v1.0') + end + + context 'when no version matches the name' do + it 'returns empty response' do + versions = described_class.by_name('does_not_exist') + + expect(versions).to be_empty + end + end + end + describe '.order_by_created_at_asc' do it 'returns versions ordered by created_at ascending' do versions = described_class.order_by_created_at_asc @@ -127,9 +144,9 @@ RSpec.describe Ci::Catalog::Resources::Version, type: :model, feature_category: describe '#name' do it 'is equivalent to release.tag' do - release_v1_0.update!(name: 'Release v1.0') + v1_0.release.update!(name: 'Release v1.0') - expect(v1_0.name).to eq(release_v1_0.tag) + expect(v1_0.name).to eq(v1_0.release.tag) end end @@ -142,10 +159,17 @@ RSpec.describe Ci::Catalog::Resources::Version, type: :model, feature_category: context 'when the sha is nil' do it 'returns nil' do - release_v1_0.update!(sha: nil) + v1_0.release.update!(sha: nil) is_expected.to be_nil end end end + + describe '#readme' do + it 'returns the correct readme for the version' do + expect(v1_0.readme.data).to include('Readme v1.0') + expect(v1_1.readme.data).to include('Readme v1.1') + end + end end diff --git a/spec/requests/api/graphql/ci/catalog/resource_spec.rb b/spec/requests/api/graphql/ci/catalog/resource_spec.rb index 24f9b6031f4..e97f09aa1d4 100644 --- a/spec/requests/api/graphql/ci/catalog/resource_spec.rb +++ b/spec/requests/api/graphql/ci/catalog/resource_spec.rb @@ -22,7 +22,7 @@ RSpec.describe 'Query.ciCatalogResource', feature_category: :pipeline_compositio ) end - let_it_be(:resource) { create(:ci_catalog_resource, :published, project: project) } + let_it_be_with_reload(:resource) { create(:ci_catalog_resource, :published, project: project) } let(:query) do <<~GQL @@ -155,41 +155,61 @@ RSpec.describe 'Query.ciCatalogResource', feature_category: :pipeline_compositio end end - describe 'versions' do - let(:query) do - <<~GQL - query { - ciCatalogResource(id: "#{resource.to_global_id}") { - id - versions { - nodes { - id - name - path - releasedAt - author { + describe 'version fields' do + before_all do + # To test the readme_html field, we need to create versions with real commit shas + project.repository.create_branch('branch_v2', project.default_branch) + project.repository.update_file( + user, 'README.md', 'Readme v2', message: 'Update readme', branch_name: 'branch_v2') + + project.repository.add_tag(user, 'v1', project.default_branch) + project.repository.add_tag(user, 'v2', 'branch_v2') + end + + let_it_be(:author) { create(:user, name: 'author') } + + let_it_be(:version1) do + create(:release, :with_catalog_resource_version, + project: project, + tag: 'v1', + sha: project.commit('v1').sha, + released_at: '2023-01-01T00:00:00Z', + author: author + ).catalog_resource_version + end + + let_it_be(:version2) do + create(:release, :with_catalog_resource_version, + project: project, + tag: 'v2', + sha: project.commit('v2').sha, + released_at: '2023-02-01T00:00:00Z', + author: author + ).catalog_resource_version + end + + describe 'versions' do + let(:query) do + <<~GQL + query { + ciCatalogResource(id: "#{resource.to_global_id}") { + id + versions { + nodes { id name - webUrl + path + releasedAt + author { + id + name + webUrl + } } } } } - } - GQL - end - - context 'when the resource has versions' do - let_it_be(:author) { create(:user, name: 'author') } - - let_it_be(:version1) do - create(:release, :with_catalog_resource_version, project: project, released_at: '2023-01-01T00:00:00Z', - author: author).catalog_resource_version - end - - let_it_be(:version2) do - create(:release, :with_catalog_resource_version, project: project, released_at: '2023-02-01T00:00:00Z', - author: author).catalog_resource_version + GQL end it 'returns the resource with the versions data' do @@ -216,53 +236,110 @@ RSpec.describe 'Query.ciCatalogResource', feature_category: :pipeline_compositio ) ) end - end - context 'when the resource does not have a version' do - it 'returns versions as an empty array' do - post_query + context 'when the readmeHtml field is requested on more than one version' do + let(:query) do + <<~GQL + query { + ciCatalogResource(fullPath: "#{resource.project.full_path}") { + versions { + nodes { + readmeHtml + } + } + } + } + GQL + end - expect(graphql_data_at(:ciCatalogResource)).to match( - a_graphql_entity_for(resource, versions: { 'nodes' => [] }) - ) + it 'limits the request to 1 version at a time' do + post_query + + expect_graphql_errors_to_include \ + [/"readmeHtml" field can be requested only for 1 CiCatalogResourceVersion\(s\) at a time./] + end + end + + context 'when the name argument is provided' do + let(:name) { 'v1' } + + let(:query) do + <<~GQL + query { + ciCatalogResource(fullPath: "#{resource.project.full_path}") { + versions(name: "#{name}") { + nodes { + id + name + path + releasedAt + readmeHtml + } + } + } + } + GQL + end + + it 'returns the version that matches the name' do + post_query + + expect(graphql_data_at(:ciCatalogResource, :versions, :nodes)).to contain_exactly( + a_graphql_entity_for( + version1, + name: version1.name, + path: project_tag_path(project, version1.name), + releasedAt: version1.released_at, + readmeHtml: a_string_including( + "#{project.full_path}/-/blob/#{project.default_branch}/README.md" + ) + ) + ) + end + + context 'when no version matches the name' do + let(:name) { 'does_not_exist' } + + it 'returns an empty array' do + post_query + + expect(graphql_data_at(:ciCatalogResource, :versions, :nodes)).to eq([]) + end + end + end + + context 'when the resource does not have a version' do + it 'returns an empty array' do + resource.versions.delete_all(:delete_all) + + post_query + + expect(graphql_data_at(:ciCatalogResource, :versions, :nodes)).to eq([]) + end end end - end - describe 'latestVersion' do - let(:query) do - <<~GQL - query { - ciCatalogResource(id: "#{resource.to_global_id}") { - id - latestVersion { + describe 'latestVersion' do + let(:query) do + <<~GQL + query { + ciCatalogResource(id: "#{resource.to_global_id}") { id - name - path - releasedAt - author { + latestVersion { id name - webUrl + path + releasedAt + readmeHtml + author { + id + name + webUrl + } } } } - } - GQL - end - - context 'when the resource has versions' do - let_it_be(:author) { create(:user, name: 'author') } - - let_it_be(:latest_version) do - create(:release, :with_catalog_resource_version, project: project, released_at: '2023-02-01T00:00:00Z', - author: author).catalog_resource_version - end - - before_all do - # Previous version of the catalog resource - create(:release, :with_catalog_resource_version, project: project, released_at: '2023-01-01T00:00:00Z', - author: author) + GQL end it 'returns the resource with the latest version data' do @@ -272,24 +349,27 @@ RSpec.describe 'Query.ciCatalogResource', feature_category: :pipeline_compositio a_graphql_entity_for( resource, latestVersion: a_graphql_entity_for( - latest_version, - name: latest_version.name, - path: project_tag_path(project, latest_version.name), - releasedAt: latest_version.released_at, + version2, + name: version2.name, + path: project_tag_path(project, version2.name), + releasedAt: version2.released_at, + readmeHtml: a_string_including('Readme v2'), author: a_graphql_entity_for(author, :name) ) ) ) end - end - context 'when the resource does not have a version' do - it 'returns nil' do - post_query + context 'when the resource does not have a version' do + it 'returns nil' do + resource.versions.delete_all(:delete_all) - expect(graphql_data_at(:ciCatalogResource)).to match( - a_graphql_entity_for(resource, latestVersion: nil) - ) + post_query + + expect(graphql_data_at(:ciCatalogResource)).to match( + a_graphql_entity_for(resource, latestVersion: nil) + ) + end end end end diff --git a/spec/support/shared_contexts/ci/catalog/resources/version_shared_context.rb b/spec/support/shared_contexts/ci/catalog/resources/version_shared_context.rb index 3eeaa52d221..a451608a5cc 100644 --- a/spec/support/shared_contexts/ci/catalog/resources/version_shared_context.rb +++ b/spec/support/shared_contexts/ci/catalog/resources/version_shared_context.rb @@ -1,33 +1,42 @@ # frozen_string_literal: true +# This context generates two catalog resources, each with two releases/versions. +# `resource1` has versions `v1.0` and `v1.1`, with releases that have real commit shas. +# `resource2` has versions `v2.0` and `v2.1`. RSpec.shared_context 'when there are catalog resources with versions' do let_it_be(:current_user) { create(:user) } - let_it_be(:project1) { create(:project, :repository, name: 'A') } - let_it_be(:project2) { create(:project, :repository, name: 'Z') } - let_it_be(:project3) { create(:project, :repository, name: 'L', description: 'Z') } + let_it_be(:project1) { create(:project, :custom_repo, files: { 'README.md' => 'Readme v1.0' }) } + let_it_be(:project2) { create(:project, :repository) } + let_it_be_with_reload(:resource1) { create(:ci_catalog_resource, project: project1) } let_it_be_with_reload(:resource2) { create(:ci_catalog_resource, project: project2) } - let_it_be(:resource3) { create(:ci_catalog_resource, project: project3) } - let_it_be_with_reload(:release_v1_0) { create(:release, project: project1, tag: 'v1.0', released_at: 4.days.ago) } - let_it_be(:release_v1_1) { create(:release, project: project1, tag: 'v1.1', released_at: 3.days.ago) } - let_it_be(:release_v2_0) { create(:release, project: project2, tag: 'v2.0', released_at: 2.days.ago) } - let_it_be(:release_v2_1) { create(:release, project: project2, tag: 'v2.1', released_at: 1.day.ago) } + let(:v1_0) { resource1.versions.by_name('v1.0').first } + let(:v1_1) { resource1.versions.by_name('v1.1').first } + let(:v2_0) { resource2.versions.by_name('v2.0').first } + let(:v2_1) { resource2.versions.by_name('v2.1').first } - let_it_be(:v1_0) do - create(:ci_catalog_resource_version, catalog_resource: resource1, release: release_v1_0, created_at: 1.day.ago) - end + before_all do + project1.repository.create_branch('branch_v1.1', project1.default_branch) - let_it_be(:v1_1) do - create(:ci_catalog_resource_version, catalog_resource: resource1, release: release_v1_1, created_at: 2.days.ago) - end + project1.repository.update_file( + current_user, 'README.md', 'Readme v1.1', message: 'Update readme', branch_name: 'branch_v1.1') - let_it_be(:v2_0) do - create(:ci_catalog_resource_version, catalog_resource: resource2, release: release_v2_0, created_at: 3.days.ago) - end + tag_v1_0 = project1.repository.add_tag(current_user, 'v1.0', project1.default_branch) + tag_v1_1 = project1.repository.add_tag(current_user, 'v1.1', 'branch_v1.1') + + release_v1_0 = create(:release, project: project1, tag: 'v1.0', released_at: 4.days.ago, + sha: tag_v1_0.dereferenced_target.sha) + release_v1_1 = create(:release, project: project1, tag: 'v1.1', released_at: 3.days.ago, + sha: tag_v1_1.dereferenced_target.sha) + + release_v2_0 = create(:release, project: project2, tag: 'v2.0', released_at: 2.days.ago) + release_v2_1 = create(:release, project: project2, tag: 'v2.1', released_at: 1.day.ago) - let_it_be(:v2_1) do + create(:ci_catalog_resource_version, catalog_resource: resource1, release: release_v1_0, created_at: 1.day.ago) + create(:ci_catalog_resource_version, catalog_resource: resource1, release: release_v1_1, created_at: 2.days.ago) + create(:ci_catalog_resource_version, catalog_resource: resource2, release: release_v2_0, created_at: 3.days.ago) create(:ci_catalog_resource_version, catalog_resource: resource2, release: release_v2_1, created_at: 4.days.ago) end end diff --git a/vendor/gems/attr_encrypted/attr_encrypted.gemspec b/vendor/gems/attr_encrypted/attr_encrypted.gemspec index 3711b16ffcf..fa3e0e227b1 100644 --- a/vendor/gems/attr_encrypted/attr_encrypted.gemspec +++ b/vendor/gems/attr_encrypted/attr_encrypted.gemspec @@ -4,12 +4,10 @@ lib = File.expand_path('../lib/', __FILE__) $:.unshift lib unless $:.include?(lib) require 'attr_encrypted/version' -require 'date' Gem::Specification.new do |s| s.name = 'attr_encrypted' s.version = AttrEncrypted::Version.string - s.date = Date.today s.summary = 'GitLab fork of attr_encrypted' s.description = "Generates attr_accessors that encrypt and decrypt attributes transparently.\n\n |