public void retrieveApiCatalog()
        {
            Hammock.Authentication.OAuth.OAuthCredentials credentials = OAuthWorkFlow.createOAuthCredentials(OAuthType.ProtectedResource, ApiCredentials.TOKEN.token,
                                                                                                             ApiCredentials.TOKEN.secret, null, null);


            Hammock.RestClient client = new Hammock.RestClient()
            {
                Authority   = "",
                Credentials = credentials
            };

            Hammock.RestRequest request = new Hammock.RestRequest()
            {
                Path = "https://apicert.soa-proxy.deere.com/platform/"
            };

            request.AddHeader("Accept", "application/vnd.deere.axiom.v3+json");
            Hammock.RestResponse response = client.Request(request);

            ApiCatalog apiCatalog = Deserialise <ApiCatalog>(response.ContentStream);

            links = OAuthWorkFlow.linksFrom(apiCatalog);

            getFiles();

            retrieveMetadataForFile();

            downloadFileContentsAndComputeMd5();
            downloadFileInPiecesAndComputeMd5();
        }
예제 #2
0
        protected override void ExecuteImpl(string[] args)
        {
            string id = args[0];

            var catalog = ApiCatalog.Load();

            if (catalog.Apis.Any(api => api.Id == id))
            {
                throw new UserErrorException($"API {id} already exists in the API catalog.");
            }
            var serviceDirectory = ServiceDirectory.LoadFromGoogleapis();

            var service = serviceDirectory.Services.FirstOrDefault(service => service.CSharpNamespaceFromProtos == id);

            if (service is null)
            {
                var lowerWithoutCloud = id.Replace(".Cloud", "").ToLowerInvariant();
                var possibilities     = serviceDirectory.Services
                                        .Select(svc => svc.CSharpNamespaceFromProtos)
                                        .Where(ns => ns.Replace(".Cloud", "").ToLowerInvariant() == lowerWithoutCloud);
                throw new UserErrorException(
                          $"No service found for '{id}'.{Environment.NewLine}Similar possibilities (check options?): {string.Join(", ", possibilities)}");
            }

            var api = new ApiMetadata
            {
                Id          = id,
                ProtoPath   = service.ServiceDirectory,
                ProductName = service.Title.EndsWith(" API") ? service.Title[..^ 4] : service.Title,
예제 #3
0
        public void Execute(string[] args)
        {
            var root    = DirectoryLayout.DetermineRootDirectory();
            var catalog = ApiCatalog.Load();
            HashSet <string> tags;

            using (var repo = new Repository(root))
            {
                tags = new HashSet <string>(repo.Tags.Select(tag => tag.FriendlyName));
            }

            List <ApiMetadata> apisToCheck = args.Length == 0
                ? catalog.Apis.Where(api => !api.Version.EndsWith("00") && !tags.Contains($"{api.Id}-{api.Version}")).ToList()
                                             // Note: this basically validates the command line arguments.
                : args.Select(arg => catalog[arg]).ToList();

            foreach (var api in apisToCheck)
            {
                if (IgnoredApis.Contains(api.Id))
                {
                    Console.WriteLine($"Skipping check for {api.Id} as it doesn't target netstandard2.0");
                    continue;
                }
                Console.WriteLine($"Checking compatibility for {api.Id} version {api.Version}");
                var prefix           = api.Id + "-";
                var previousVersions = tags
                                       .Where(tag => tag.StartsWith(prefix))
                                       .Select(tag => tag.Split(new char[] { '-' }, 2)[1])
                                       .Where(v => !v.StartsWith("0")) // We can reasonably ignore old 0.x versions
                                       .Select(StructuredVersion.FromString)
                                       .OrderBy(v => v)
                                       .ToList();

                var newVersion = api.StructuredVersion;

                // First perform a "strict" check, where necessary, failing the build if the difference
                // is inappropriate.
                var(requiredVersion, requiredLevel) = GetRequiredCompatibility(api.StructuredVersion);
                if (requiredVersion != null)
                {
                    if (!previousVersions.Contains(requiredVersion))
                    {
                        throw new UserErrorException($"Expected to check compatibility with {requiredVersion}, but no corresponding tag found");
                    }
                    var actualLevel = CheckCompatibility(api, requiredVersion);
                    if (actualLevel < requiredLevel)
                    {
                        throw new UserErrorException($"Required compatibility level: {requiredLevel}. Actual compatibility level: {actualLevel}.");
                    }
                }

                // Next log the changes compared with the previous release (if we haven't already diffed it)
                // in an informational way. (This can be used to improve or check release notes.)
                var lastRelease = previousVersions.LastOrDefault();
                if (lastRelease != null && !lastRelease.Equals(requiredVersion))
                {
                    CheckCompatibility(api, lastRelease);
                }
            }
        }
예제 #4
0
        private static void MaybeShowStale(Repository repo, List <Tag> allTags, ApiCatalog catalog, ApiMetadata api)
        {
            string expectedTagName = $"{api.Id}-{api.Version}";
            var    latestRelease   = allTags.FirstOrDefault(tag => tag.FriendlyName == expectedTagName);

            // If we don't have any releases for the API (or couldn't find the tag), skip it.
            if (latestRelease is null)
            {
                return;
            }

            var laterCommits    = repo.Commits.TakeWhile(commit => commit.Sha != latestRelease.Target.Sha);
            var relevantCommits = laterCommits
                                  .Where(GitHelpers.CreateCommitPredicate(repo, catalog, api))
                                  .Where(commit => !CommitOverrides.IsSkipped(commit))
                                  .ToList();

            // No changes
            if (relevantCommits.Count == 0)
            {
                return;
            }

            string changes = relevantCommits.Count == 1 ? "change" : "changes";

            Console.WriteLine($"{api.Id,-50} {latestRelease.GetDate():yyyy-MM-dd}: {api.Version} + {relevantCommits.Count} {changes}");
        }
        IEnumerable <ReleaseProposal> IBatchCriterion.GetProposals(ApiCatalog catalog)
        {
            var root = DirectoryLayout.DetermineRootDirectory();

            using var repo = new Repository(root);
            var pendingChangesByApi = GitHelpers.GetPendingChangesByApi(repo, catalog);

            foreach (var api in catalog.Apis)
            {
                // Don't even bother proposing package groups at the moment.
                if (api.PackageGroup is object)
                {
                    continue;
                }
                // Don't propose packages that haven't changed.
                // Note that this will also not propose a release for APIs that haven't
                // yet *been* released - which is probably fine. (We don't want to accidentally
                // launch something due to not paying attention.)
                if (pendingChangesByApi[api].Commits.Count == 0)
                {
                    continue;
                }
                var newVersion = api.StructuredVersion.AfterIncrement();

                yield return(ReleaseProposal.CreateFromHistory(repo, api.Id, newVersion));
            }
        }
예제 #6
0
        public void retrieveApiCatalogToEstablishOAuthProviderDetails()
        {
            Hammock.Authentication.OAuth.OAuthCredentials credentials = createOAuthCredentials(OAuthType.ProtectedResource, null, null, null, null);

            Hammock.RestClient client = new Hammock.RestClient()
            {
                Authority   = "https://apicert.soa-proxy.deere.com/platform/",
                Credentials = credentials
            };

            Hammock.RestRequest request = new Hammock.RestRequest()
            {
                Path = ""
            };

            request.AddHeader("Accept", "application/vnd.deere.axiom.v3+json");
            Hammock.RestResponse response = client.Request(request);

            MemoryStream stream1           = new MemoryStream();
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ApiCatalog));

            stream1.Position = 0;
            ApiCatalog apiCatalog = (ApiCatalog)ser.ReadObject(response.ContentStream);

            links = linksFrom(apiCatalog);
        }
예제 #7
0
        protected override void ExecuteImpl(string[] args)
        {
            ValidateCommonHiddenProductionDependencies();
            var root    = DirectoryLayout.DetermineRootDirectory();
            var catalog = ApiCatalog.Load();

            ValidateApiCatalog(catalog);
            Console.WriteLine($"API catalog contains {catalog.Apis.Count} entries");
            // Now we know we can parse the API catalog, let's reformat it.
            ReformatApiCatalog(catalog);
            RewriteReadme(catalog);
            RewriteRenovate(catalog);
            HashSet <string> apiNames = catalog.CreateIdHashSet();

            foreach (var api in catalog.Apis)
            {
                var path = Path.Combine(root, "apis", api.Id);
                GenerateProjects(path, api, apiNames);
                GenerateSolutionFiles(path, api);
                GenerateDocumentationStub(path, api);
                GenerateSynthConfiguration(path, api);
                GenerateOwlBotConfiguration(path, api);
                GenerateMetadataFile(path, api);
            }
        }
        private static void Execute(string id)
        {
            var catalog = ApiCatalog.Load();
            var api     = catalog[id];

            if (api.NoVersionHistory)
            {
                Console.WriteLine($"Skipping version history update for {id}");
                return;
            }
            string historyFilePath = HistoryFile.GetPathForPackage(id);

            var root = DirectoryLayout.DetermineRootDirectory();

            using var repo = new Repository(root);
            var releases         = Release.LoadReleases(repo, catalog, api).ToList();
            var historyFile      = HistoryFile.Load(historyFilePath);
            var sectionsInserted = historyFile.MergeReleases(releases);

            if (sectionsInserted.Count != 0)
            {
                historyFile.Save(historyFilePath);
                var relativePath = Path.GetRelativePath(DirectoryLayout.DetermineRootDirectory(), historyFilePath)
                                   .Replace('\\', '/');
                Console.WriteLine($"Updated version history file: {relativePath}");
                Console.WriteLine("New content:");
                Console.WriteLine();
                foreach (var line in sectionsInserted.SelectMany(section => section.Lines))
                {
                    Console.WriteLine(line);
                }
            }
        }
        private static void Execute(string id)
        {
            var catalog = ApiCatalog.Load();
            var api     = catalog[id];

            if (api.NoVersionHistory)
            {
                Console.WriteLine($"Skipping version history update for {id}");
                return;
            }
            string historyFilePath = HistoryFile.GetPathForPackage(id);

            var root = DirectoryLayout.DetermineRootDirectory();

            using (var repo = new Repository(root))
            {
                var releases = LoadReleases(repo, api).ToList();
                if (!File.Exists(historyFilePath))
                {
                    File.WriteAllText(historyFilePath, "# Version history\r\n\r\n");
                }
                var historyFile = HistoryFile.Load(historyFilePath);
                historyFile.MergeReleases(releases);
                historyFile.Save(historyFilePath);
            }
            var relativePath = Path.GetRelativePath(DirectoryLayout.DetermineRootDirectory(), historyFilePath)
                               .Replace('\\', '/');

            Console.WriteLine($"Updated version history file: {relativePath}");
        }
예제 #10
0
        private static void SetVersion(string id, string version)
        {
            var catalog = ApiCatalog.Load();
            var api     = catalog[id];

            string oldVersion = api.Version;

            api.Version = version;
            var layout   = DirectoryLayout.ForApi(id);
            var apiNames = catalog.CreateIdHashSet();

            ProjectGenerator.Program.GenerateMetadataFile(layout.SourceDirectory, api);
            ProjectGenerator.Program.GenerateProjects(layout.SourceDirectory, api, apiNames);
            ProjectGenerator.Program.RewriteReadme(catalog);
            ProjectGenerator.Program.RewriteDocsRootIndex(catalog);

            // Update the parsed JObject associated with the ID, and write it back to apis.json.
            api.Json["version"] = version;
            string formatted = catalog.FormatJson();

            File.WriteAllText(ApiCatalog.CatalogPath, formatted);
            Console.WriteLine("Updated apis.json");
            Console.WriteLine();
            Console.WriteLine(new ApiVersionPair(id, oldVersion, version));
        }
예제 #11
0
        protected override void ExecuteImpl(string[] args)
        {
            string id = args[0];

            var catalog = ApiCatalog.Load();

            if (catalog.Apis.Any(api => api.Id == id))
            {
                throw new UserErrorException($"API {id} already exists in the API catalog.");
            }
            var root       = DirectoryLayout.DetermineRootDirectory();
            var googleapis = Path.Combine(root, "googleapis");
            var apiIndex   = ApiIndex.V1.Index.LoadFromGoogleApis(googleapis);

            var targetApi = apiIndex.Apis.FirstOrDefault(api => api.DeriveCSharpNamespace() == id);

            if (targetApi is null)
            {
                var lowerWithoutCloud = id.Replace(".Cloud", "").ToLowerInvariant();
                var possibilities     = apiIndex.Apis
                                        .Select(api => api.DeriveCSharpNamespace())
                                        .Where(ns => ns.Replace(".Cloud", "").ToLowerInvariant() == lowerWithoutCloud);
                throw new UserErrorException(
                          $"No service found for '{id}'.{Environment.NewLine}Similar possibilities (check options?): {string.Join(", ", possibilities)}");
            }

            var api = new ApiMetadata
            {
                Id          = id,
                ProtoPath   = targetApi.Directory,
                ProductName = targetApi.Title.EndsWith(" API") ? targetApi.Title[..^ 4] : targetApi.Title,
예제 #12
0
        public void retrieveApiCatalogToEstablishOAuthProviderDetails(string endPoint)
        {
            //Hammock.Authentication.OAuth.OAuthCredentials credentials = createOAuthCredentials(OAuthType.ProtectedResource, null, null, null, null);

            Hammock.RestClient client = new Hammock.RestClient()
            {
                Authority = endPoint,
                //Credentials = credentials
            };

            client.AddHeader("Accept", "application/json");
            client.AddHeader("authorization", $"Basic {GetBase64EncodedClientCredentials()}");

            Hammock.RestRequest request = new Hammock.RestRequest()
            {
                Path = ""
            };

            request.AddHeader("Accept", "application/vnd.deere.axiom.v3+json");
            using (Hammock.RestResponse response = client.Request(request))
            {
                //Logger.Log(response);
                MemoryStream stream1           = new MemoryStream();
                DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ApiCatalog));

                stream1.Position = 0;
                ApiCatalog apiCatalog = (ApiCatalog)ser.ReadObject(response.ContentStream);

                links = linksFrom(apiCatalog);
            }
        }
예제 #13
0
        protected override void ExecuteImpl(string[] args)
        {
            string configFile = args[0];
            var    json       = File.ReadAllText(configFile);
            var    config     = JsonConvert.DeserializeObject <BatchReleaseConfig>(json);

            var criteria = config.GetCriteria().ToList();

            if (criteria.Count != 1)
            {
                throw new UserErrorException("Batch release config must specify exactly one criterion.");
            }

            if (!config.DryRun)
            {
                var root = DirectoryLayout.DetermineRootDirectory();
                using var repo = new Repository(root);

                if (repo.RetrieveStatus().IsDirty)
                {
                    throw new UserErrorException("In non-dry-run mode, the current branch must not have changes.");
                }
            }

            var catalog   = ApiCatalog.Load();
            var criterion = criteria[0];
            var proposals = criterion.GetProposals(catalog);

            foreach (var proposal in proposals)
            {
                // Note: This takes into account the dry-run flag.
                proposal.Execute(config);
            }
        }
        /// <summary>
        /// Updates the dependencies in an API for known packages, but only if the default
        /// version is later than the current one, with the same major version number.
        /// </summary>
        public static void UpdateDependencies(ApiCatalog catalog, ApiMetadata api)
        {
            // Update any previously-defaulted versions to be explicit, if the new version is GA.
            // (This only affects production dependencies, so is not performed in UpdateDependencyDictionary.)
            // Implicit dependencies are always present in DefaultPackageVersions, so we don't need to worry about
            // "internal" dependencies.
            if (api.IsReleaseVersion && PackageTypeToImplicitDependencies.TryGetValue(api.Type, out var implicitDependencies))
            {
                foreach (var implicitDependency in implicitDependencies)
                {
                    if (!api.Dependencies.ContainsKey(implicitDependency))
                    {
                        api.Dependencies[implicitDependency] = DefaultPackageVersions[implicitDependency];
                    }
                }
            }

            UpdateDependencyDictionary(api.Dependencies, "dependencies");
            UpdateDependencyDictionary(api.TestDependencies, "testDependencies");

            void UpdateDependencyDictionary(SortedDictionary <string, string> dependencies, string jsonName)
            {
                if (dependencies.Count == 0)
                {
                    return;
                }

                // We want to update any dependencies to "external" packages as listed in DefaultPackageVersions,
                // but also "internal" packages such as Google.LongRunning.
                Dictionary <string, string> allDefaultPackageVersions = DefaultPackageVersions
                                                                        .Concat(catalog.Apis.Select(api => new KeyValuePair <string, string>(api.Id, api.Version)))
                                                                        .ToDictionary(pair => pair.Key, pair => pair.Value);

                foreach (var package in dependencies.Keys.ToList())
                {
                    if (allDefaultPackageVersions.TryGetValue(package, out var defaultVersion))
                    {
                        var currentVersion = dependencies[package];
                        if (currentVersion == DefaultVersionValue ||
                            currentVersion == ProjectVersionValue ||
                            defaultVersion == currentVersion)
                        {
                            continue;
                        }
                        var structuredDefaultVersion = StructuredVersion.FromString(defaultVersion);
                        var structuredCurrentVersion = StructuredVersion.FromString(currentVersion);
                        if (structuredDefaultVersion.CompareTo(structuredCurrentVersion) > 0 &&
                            structuredDefaultVersion.Major == structuredCurrentVersion.Major)
                        {
                            dependencies[package] = defaultVersion;
                        }
                    }
                }

                if (api.Json is object)
                {
                    api.Json[jsonName] = new JObject(dependencies.Select(pair => new JProperty(pair.Key, pair.Value)));
                }
            }
        }
        IEnumerable <ReleaseProposal> IBatchCriterion.GetProposals(ApiCatalog catalog)
        {
            var root = DirectoryLayout.DetermineRootDirectory();

            using var repo = new Repository(root);
            var pendingChangesByApi = GitHelpers.GetPendingChangesByApi(repo, catalog);

            foreach (var api in catalog.Apis)
            {
                var pendingChanges = pendingChangesByApi[api];
                var pendingCommits = pendingChanges.Commits.Select(commit => commit.HashPrefix);
                if (!Commits.SetEquals(pendingCommits))
                {
                    continue;
                }
                var newVersion = api.StructuredVersion.AfterIncrement();
                var proposal   = ReleaseProposal.CreateFromHistory(repo, api.Id, newVersion);

                // Potentially replace the natural history with an override
                if (!string.IsNullOrEmpty(HistoryOverride) && proposal.NewHistorySection is HistoryFile.Section newSection)
                {
                    var naturalLines  = newSection.Lines;
                    var overrideLines = HistoryOverride.Split('\n');
                    var lines         = naturalLines.Take(2).Concat(overrideLines).ToList();
                    // We always add a blank line at the end of each section.
                    lines.Add("");
                    proposal.NewHistorySection = new HistoryFile.Section(newVersion, lines);
                }
                yield return(proposal);
            }
        }
예제 #16
0
        /// <summary>
        /// Generates the docfx-devsite.json file used to generate just the metadata for DevSite.
        /// </summary>
        private static void CreateDevsiteDocfxJson(ApiCatalog catalog, ApiMetadata rootApi, string outputDirectory)
        {
            // Pick whichever framework is listed first. (This could cause problems if a dependency
            // doesn't target the given framework, but that seems unlikely.)
            // Default to netstandard2.0 if nothing is listed.
            string targetFramework = rootApi.TargetFrameworks?.Split(';').First() ?? "netstandard2.0";

            var json = new JObject
            {
                ["metadata"] = new JArray {
                    new JObject
                    {
                        ["src"] = new JObject
                        {
                            ["files"] = new JArray {
                                $"{rootApi.Id}/{rootApi.Id}.csproj"
                            },
                            ["cwd"] = $"../../../apis/{rootApi.Id}"
                        },
                        ["dest"]       = "obj/bareapi",
                        ["filter"]     = "filterConfig.yml",
                        ["properties"] = new JObject {
                            ["TargetFramework"] = targetFramework
                        }
                    },
                }
            };

            File.WriteAllText(Path.Combine(outputDirectory, "docfx-devsite.json"), json.ToString());
        }
예제 #17
0
        protected override void ExecuteImpl(string[] args)
        {
            string id      = args[0];
            string version = args[1];

            var catalog = ApiCatalog.Load();
            var api     = catalog[id];

            string oldVersion = api.Version;

            api.Version = version;
            var layout   = DirectoryLayout.ForApi(id);
            var apiNames = catalog.CreateIdHashSet();

            GenerateProjectsCommand.GenerateMetadataFile(layout.SourceDirectory, api);
            GenerateProjectsCommand.GenerateProjects(layout.SourceDirectory, api, apiNames);
            GenerateProjectsCommand.RewriteReadme(catalog);
            GenerateProjectsCommand.RewriteDocsRootIndex(catalog);

            // Update the parsed JObject associated with the ID, and write it back to apis.json.
            api.Json["version"] = version;
            string formatted = catalog.FormatJson();

            File.WriteAllText(ApiCatalog.CatalogPath, formatted);
            Console.WriteLine("Updated apis.json");
            Console.WriteLine();
            Console.WriteLine(new ApiVersionPair(id, oldVersion, version));
        }
예제 #18
0
        /// <summary>
        /// Given a set of APIs we're generating docs for, find transitive external dependencies that we need to include in the doc set (if we have them).
        /// </summary>
        private static IEnumerable <string> GetExternalDependencies(ApiCatalog catalog, IEnumerable <string> apiIds)
        {
            var directExternalDependencies = apiIds
                                             .Select(id => catalog[id])
                                             .SelectMany(api => api.Dependencies.Keys)
                                             .Intersect(s_externalDependencies.Keys);
            HashSet <string> set             = new HashSet <string>();
            Queue <string>   processingQueue = new Queue <string>();

            foreach (var directDependency in directExternalDependencies)
            {
                processingQueue.Enqueue(directDependency);
            }

            while (processingQueue.TryDequeue(out var next))
            {
                if (set.Add(next))
                {
                    if (s_externalDependencies.TryGetValue(next, out var childDependencies))
                    {
                        foreach (var child in childDependencies)
                        {
                            processingQueue.Enqueue(child);
                        }
                    }
                }
            }
            return(set);
        }
        public static void RewriteDocsRootIndex(ApiCatalog catalog)
        {
            var root      = DirectoryLayout.ForRootDocs().DocsSourceDirectory;
            var indexPath = Path.Combine(root, "index.md");

            RewriteApiTable(indexPath, catalog, api => $"{api.Id}/index.html");
        }
        internal void InternalExecute(string id, string version, bool quiet)
        {
            var catalog = ApiCatalog.Load();
            var api     = catalog[id];

            string oldVersion = api.Version;

            api.Version = version;
            if (api.StructuredVersion.Patch == 0)
            {
                GenerateProjectsCommand.UpdateDependencies(catalog, api);
            }
            var layout   = DirectoryLayout.ForApi(id);
            var apiNames = catalog.CreateIdHashSet();

            // This will still write output, even if "quiet" is true, but that's probably
            // okay for batch releasing.
            GenerateProjectsCommand.GenerateMetadataFile(layout.SourceDirectory, api);
            GenerateProjectsCommand.GenerateProjects(layout.SourceDirectory, api, apiNames);
            GenerateProjectsCommand.RewriteReadme(catalog);

            // Update the parsed JObject associated with the ID, and write it back to apis.json.
            api.Json["version"] = version;
            string formatted = catalog.FormatJson();

            File.WriteAllText(ApiCatalog.CatalogPath, formatted);
            if (!quiet)
            {
                Console.WriteLine("Updated apis.json");
                Console.WriteLine();
                Console.WriteLine(new ApiVersionPair(id, oldVersion, version));
            }
        }
        public static void RewriteReadme(ApiCatalog catalog)
        {
            var root       = DirectoryLayout.DetermineRootDirectory();
            var readmePath = Path.Combine(root, "README.md");

            RewriteApiTable(readmePath, catalog, api => $"https://googleapis.dev/dotnet/{api.Id}/{api.Version}");
        }
예제 #22
0
        private static int MainImpl(string[] args)
        {
            if (args.Length != 1)
            {
                throw new UserErrorException("Please specify the API name");
            }
            string api         = args[0];
            var    layout      = DirectoryLayout.ForApi(api);
            var    apiCatalog  = ApiCatalog.Load();
            var    apiMetadata = apiCatalog[api];

            string output = layout.DocsOutputDirectory;

            if (Directory.Exists(output))
            {
                Directory.Delete(output, true);
            }
            Directory.CreateDirectory(output);

            CreateGoogleApisDevDocfxJson(apiCatalog, apiMetadata, output);
            CreateDevsiteDocfxJson(apiCatalog, apiMetadata, output);
            CopyAndGenerateArticles(apiMetadata, layout.DocsSourceDirectory, output);
            CreateToc(api, output);
            return(0);
        }
        protected override void ExecuteImpl(string[] args)
        {
            var catalog       = ApiCatalog.Load();
            var root          = DirectoryLayout.DetermineRootDirectory();
            var googleapis    = Path.Combine(root, "googleapis");
            var apiIndex      = ApiIndex.V1.Index.LoadFromGoogleApis(googleapis);
            int modifiedCount = 0;

            foreach (var api in catalog.Apis)
            {
                var indexEntry = apiIndex.Apis.FirstOrDefault(x => x.DeriveCSharpNamespace() == api.Id);
                if (indexEntry is null)
                {
                    continue;
                }

                // Change this line when introducing a new field...
                api.Json.Last.AddAfterSelf(new JProperty("serviceConfigFile", indexEntry.ConfigFile));
                modifiedCount++;
            }

            Console.WriteLine($"Modified APIs: {modifiedCount}");
            string json = catalog.FormatJson();

            // Validate that we can still load it, before saving it to disk...
            ApiCatalog.FromJson(json);

            File.WriteAllText(ApiCatalog.CatalogPath, json);
        }
예제 #24
0
        private async Task <ApiCatalog> LoadCatalog()
        {
            var allContents = await _client.Repository.Content.GetAllContentsByRef(RepositoryOwner, RepositoryName, ApiCatalog.RelativeCatalogPath, _config.Committish);

            var json = allContents.Single().Content;

            return(ApiCatalog.FromJson(json));
        }
        protected override void ExecuteImpl(string[] args)
        {
            string id = args[0];

            var catalog = ApiCatalog.Load();
            var api     = catalog[id];

            Console.WriteLine($"Current version of {id} in the API catalog: {api.Version}");
        }
예제 #26
0
        private Program(string apiId)
        {
            DirectoryLayout layout = DirectoryLayout.ForApi(apiId);

            _apiId       = apiId;
            _outputRoot  = layout.DocsOutputDirectory;
            _devSiteRoot = Path.Combine(_outputRoot, "devsite");
            _apiCatalog  = ApiCatalog.Load();
            _apiIds      = _apiCatalog.CreateIdHashSet();
        }
예제 #27
0
        public void Execute(string[] args)
        {
            var root    = DirectoryLayout.DetermineRootDirectory();
            var catalog = ApiCatalog.Load();
            HashSet <string> tags;

            using (var repo = new Repository(root))
            {
                tags = new HashSet <string>(repo.Tags.Select(tag => tag.FriendlyName));
            }

            List <ApiMetadata> apisToCheck = args.Length == 0
                ? catalog.Apis.Where(api => !api.Version.EndsWith("00") && !tags.Contains($"{api.Id}-{api.Version}")).ToList()
                                             // Note: this basically validates the command line arguments.
                : args.Select(arg => catalog[arg]).ToList();

            foreach (var api in apisToCheck)
            {
                Console.WriteLine($"Checking compatibility for {api.Id} version {api.Version}");
                var prefix      = api.Id + "-";
                var lastVersion = tags
                                  .Where(tag => tag.StartsWith(prefix))
                                  .Select(tag => tag.Split(new char[] { '-' }, 2)[1])
                                  .Where(v => !v.StartsWith("0")) // We can reasonably ignore old 0.x versions
                                  .Select(StructuredVersion.FromString)
                                  .OrderBy(v => v)
                                  .LastOrDefault();

                if (lastVersion is null)
                {
                    Console.WriteLine("No previous versions released; ignoring.");
                    continue;
                }

                var newVersion = api.StructuredVersion;

                // If we're releasing a new version, we should check against the previous one.
                // (For example, if this PR creates 1.2.0, then check against 1.1.0.)
                // Otherwise, just expect minor changes.
                Level requiredLevel = Level.Minor;
                if (!lastVersion.Equals(newVersion))
                {
                    requiredLevel =
                        lastVersion.Major != newVersion.Major ? Level.Major   // Major version bump: anything goes
                        : lastVersion.Minor != newVersion.Minor ? Level.Minor // Minor version bump: minor changes are okay
                        : Level.Identical;                                    // Patch version bump: API should be identical
                }

                var actualLevel = CheckCompatibility(api, lastVersion);
                if (actualLevel < requiredLevel)
                {
                    throw new UserErrorException($"Required compatibility level: {requiredLevel}. Actual compatibility level: {actualLevel}.");
                }
            }
        }
        protected override void ExecuteImpl(string[] args)
        {
            var catalog = ApiCatalog.Load();
            var lagging = catalog.Apis.Where(api => api.CanHaveGaRelease && api.StructuredVersion.Prerelease is string);

            Console.WriteLine($"Lagging packages:");
            foreach (var api in lagging)
            {
                Console.WriteLine($"{api.Id} ({api.Version})");
            }
        }
        public static void RewriteRenovate(ApiCatalog catalog)
        {
            var     root = DirectoryLayout.DetermineRootDirectory();
            string  path = Path.Combine(root, ".github", "renovate.json");
            string  json = File.ReadAllText(path);
            JObject jobj = JObject.Parse(json);

            jobj["ignorePaths"] = new JArray(catalog.Apis.Select(api => $"apis/{api.Id}/{api.Id}/**").ToArray());
            json = jobj.ToString(Formatting.Indented);
            File.WriteAllText(path, json);
        }
        private static void ReformatApiCatalog(ApiCatalog catalog)
        {
            string path      = ApiCatalog.CatalogPath;
            string existing  = File.ReadAllText(path);
            string formatted = catalog.FormatJson();

            if (existing != formatted)
            {
                File.WriteAllText(path, formatted);
                Console.WriteLine("Reformatted apis.json");
            }
        }
예제 #31
0
 public ApiBootstrapper(
     IEnumerable<KeyValuePair<Type, Func<IHttpApiRequestContext, INancyModule>>> nancyModules)
 {
     _apiCatalog = new ApiCatalog(nancyModules);
 }