{
    "version": "https://jsonfeed.org/version/1",
    "title": "Packit Blog",
    "home_page_url": "https://packit.dev/posts",
    "description": "Blog posts by Packit",
    "items": [
        {
            "id": "https://packit.dev/posts/code-review",
            "content_html": "<p>One amazing benefit that modern LLMs come with is using them as a linter, or a pair programmer. You can easily get feedback on your code: just share it with the AI tool and ask a question. If the feedback is solid, your code is improved. If the feedback is poor, you can just disregard it. But overall with very little effort you can gain a lot.</p><p>In this article we are going to focus on code review done with AI tools. We are going to explore a few solutions available as of February 2026 and how they compare based on our experience. This is not a thorough analysis nor are we doing any evals.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"gemini-code-assist\"><a href=\"https://github.com/marketplace/gemini-code-assist\" target=\"_blank\" rel=\"noopener noreferrer\">Gemini-code-assist</a><a href=\"#gemini-code-assist\" class=\"hash-link\" aria-label=\"Direct link to gemini-code-assist\" title=\"Direct link to gemini-code-assist\">​</a></h2><p>Our AI tool of choice for our upstream reviews is Gemini-code-assist. It's free, easy to set up, and you get to see the comments inside the GitHub interface. Since it's powered by the Gemini models, it can provide solid feedback. If your PR contains clear mistakes, this tool can easily find them. On top of that, we had multiple instances when Gemini discovered subtle issues that were not obvious to the author or a reviewer which turned out to be real problems. Therefore it prevented real bugs from happening in our production environment.</p><p>On the other hand, it can be quite opinionated with suggestions that are either irrelevant or don't match your project. That's not strictly a bad thing. Gemini often brings up technical debt and comments on complexity of pull requests. These comments can start a very productive discussion and help the team battle technical debt and invent solutions that can be easily maintained long term.</p><p><a href=\"https://github.com/jpodivin\" target=\"_blank\" rel=\"noopener noreferrer\">Jiri Podivin</a> recently <a href=\"https://github.com/packit/packit-service/commit/80470bd6c41f49b8fff9950af3e758c64c9df77c\" target=\"_blank\" rel=\"noopener noreferrer\">contributed a style guide</a> to help Gemini with the reviews. Over the few weeks we only saw a handful of occasions when Gemini would take it into account:</p><p><img loading=\"lazy\" alt=\"Gemini referencing the style guide\" src=\"/assets/images/gemini_ref-541e4ee378d41e92f9999bd9086959be.png\" width=\"1796\" height=\"885\" class=\"img_ev3q\"></p><p>It's possible to run this tool locally in your IDE, but if that's not your local development workflow, it's easier to just open a PR.</p><p>But overall, Gemini-code-assist is an amazing tool that is easy to set up, easy to use, it's free and provides real benefit.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"claude-code\">Claude Code<a href=\"#claude-code\" class=\"hash-link\" aria-label=\"Direct link to Claude Code\" title=\"Direct link to Claude Code\">​</a></h2><p>Let's continue with the well known Claude Code tool. It's a full-blown AI agentic system running in your terminal, so it can perform code review easily. You don't even need a fancy prompt, it can be as simple as:</p><blockquote><p>Perform a thorough code review of our latest work in commit 4b50c430861020216befeecafaebb918ac7bda1f</p></blockquote><p>Claude will inspect the commit and will create a plan for itself with tasks to accomplish the code review. It can look something like this:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">● Bash(git show 4b50c430861020216befeecafaebb918ac7bda1f --stat)</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  ⎿ &nbsp;commit 4b50c430861020216befeecafaebb918ac7bda1f</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">     Author: Tomas Tomecek &lt;ttomecek@redhat.com&gt;</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">     Date:   Fri Feb 13 10:38:14 2026 +0100</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">     … +22 lines (ctrl+o to expand)</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">● Bash(git show 4b50c430861020216befeecafaebb918ac7bda1f)</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  ⎿ &nbsp;commit 4b50c430861020216befeecafaebb918ac7bda1f</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">     Author: Tomas Tomecek &lt;ttomecek@redhat.com&gt;</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">     Date:   Fri Feb 13 10:38:14 2026 +0100</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">     … +395 lines (ctrl+o to expand)</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">● Thorough Code Review: Commit 4b50c43 \"Implement feature foobar\"</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  🔴 CRITICAL ISSUES</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  1. SYNTAX ERROR: Invalid Jinja2 Expression</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">...</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>The biggest advantage here is that if you are already using this tool (or something similar), it's just a natural part of your development workflow. Claude Code not only reviews your work, but it can also propose changes and even implement them.</p><p>This tool can be infinitely helpful, especially if your codebase is easy to navigate, is not colossal, and has solid documentation which Claude can follow.</p><p>Several people on the team use Claude Code daily and it is part of our daily job. We've gotten used to it so much that we couldn't live without it, honestly. It's so convenient and helpful. But not everyone is using it, with so many AI tools available, our personal journeys with AI tools adoption are different.</p><p>Though not everything it does is perfect and we always need to review its work and update it.</p><p>Another huge benefit here is that creating a slash command with precise description and expectations about the review is not hard. Then you can get reviews tailored specifically for you.</p><p>We have already started a repository where we gather our Claude Code slash commands: <a href=\"https://github.com/packit/internal-ai-workflows\" target=\"_blank\" rel=\"noopener noreferrer\">github.com/packit/internal-ai-workflows</a></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"ai-code-review\"><a href=\"https://gitlab.com/redhat/edge/ci-cd/ai-code-review\" target=\"_blank\" rel=\"noopener noreferrer\"><code>ai-code-review</code></a><a href=\"#ai-code-review\" class=\"hash-link\" aria-label=\"Direct link to ai-code-review\" title=\"Direct link to ai-code-review\">​</a></h2><p>This is a tool built by a Redhatter <a href=\"https://gitlab.com/juanjeojeda\" target=\"_blank\" rel=\"noopener noreferrer\">Juanje Ojeda</a>. It's a command-line tool that works with multiple AI providers (Gemini, Vertex AI, Anthropic, Ollama) and can perform code review locally or on existing pull requests on GitHub or GitLab.</p><p>I love the simplicity: you set it up once and then with a simple command you can have local code review and also set it up in your CI system. If you are a fan of the UNIX philosophy of having a single tool that does its job well, then this is the one.</p><p>Here's an example usage for a local change for this blog post:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ ai-code-review --local</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">📝 Review generated successfully!</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">================================================================================</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">AI CODE REVIEW</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">================================================================================</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">## Local Code Review</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">### 🔍 Code Analysis</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">This merge request adds a blog post about AI-powered code review tools...</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">### ✅ Summary</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">**Overall Assessment:** No critical issues identified. This is a low-risk content addition with proper documentation and minimal dependency changes. Minor suggestions provided for content improvements and link verification.</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">**Minor Suggestions:**</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- Consider adding version pinning to requirements.txt for reproducibility (e.g., pygal==3.0.0)</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- Verify the February 2026 date in the blog post is intentional and not a typo</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- Check that external links (especially github.com/packit/internal-ai-workflows) are accessible to intended readers</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- Consider adding alt text description in the markdown for the gemini_ref.png image for accessibility</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- The blog post could benefit from a brief mention of evaluation criteria used when comparing the tools</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">---</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">🤖 **AI Code Review** | Model: claude-sonnet-4-5</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">⚠️ AI-generated suggestions may be incorrect. Verify before applying.</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>I've omitted the detailed code analysis section here for brevity, but the summary gives you a good sense of the output quality and structure.</p><p>The tool is particularly valuable if you're cautious about sharing data with Cloud providers. You can run a model of your choice locally via Ollama and be completely self-sufficient.</p><p>While the summary output is well-structured, as shown above, the full detailed review can be quite verbose. Some additional formatting options (especially syntax highlighting and usage of colors), or the ability to adjust verbosity levels would be helpful for quickly scanning larger changes.</p><p>With that said, ai-code-review is a powerful tool that serves its purpose very well. Since it's an open-source project, you're welcome to open issues or contribute improvements.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"future-exploration\">Future Exploration<a href=\"#future-exploration\" class=\"hash-link\" aria-label=\"Direct link to Future Exploration\" title=\"Direct link to Future Exploration\">​</a></h2><p>We're aware of CodeRabbit, another well-known AI code review tool, but haven't had the opportunity to evaluate it yet. We may cover it in a future post.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"conclusion\">Conclusion<a href=\"#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\">​</a></h2><p>We've explored three distinct approaches to AI-based code review: Gemini-code-assist for seamless GitHub integration, Claude Code for comprehensive development assistance, and ai-code-review for maximum flexibility.</p><p><strong>Our recommendations:</strong></p><ul><li><strong>For quick PR reviews</strong>: Use Gemini-code-assist if you work primarily on GitHub and want zero-friction setup</li><li><strong>For integrated development</strong>: Use Claude Code if you want an AI assistant that can both review and implement changes as part of your workflow</li><li><strong>For flexibility and privacy</strong>: Use ai-code-review if you need multi-provider support or want to run reviews with local models</li></ul><p>Each tool excels in its domain, and the \"best\" choice depends on your workflow, privacy requirements, and how you want AI to fit into your development process. The important thing is to start incorporating AI code review into your workflow. Every review comment that AI catches is time and energy your team can redirect toward more valuable work, such as having a cup of coffee.</p><p>Even though this article was written by me, Tomas Tomecek, I captured the feedback of all the team members I received over the past several weeks.</p>",
            "url": "https://packit.dev/posts/code-review",
            "title": "Our experience with AI-based code review",
            "summary": "One amazing benefit that modern LLMs come with is using them as a linter, or a pair programmer. You can easily get feedback on your code: just share it with the AI tool and ask a question. If the feedback is solid, your code is improved. If the feedback is poor, you can just disregard it. But overall with very little effort you can gain a lot.",
            "date_modified": "2026-06-09T11:51:53.000Z",
            "author": {
                "name": "Tomáš Tomeček",
                "url": "https://github.com/TomasTomecek"
            },
            "tags": [
                "AI",
                "code-review",
                "automation",
                "development"
            ]
        },
        {
            "id": "https://packit.dev/posts/comparing-frontier-models-june2026",
            "content_html": "<p>We evaluated three Claude frontier models: Sonnet 4.6, Opus 4.6, and Opus 4.8.\nThis was done on a fixed set of five RHEL triage issues using our <a href=\"https://github.com/packit/ai-workflows/blob/main/e2e-ci-setup.md\" target=\"_blank\" rel=\"noopener noreferrer\">end-to-end\ntest\nharness</a>. The\nharness is validating our triaging agent against a fixed set of known issues.\nTriage is the first and most consequential step in the workflow: the agent reads\na Jira CVE issue and decides how it should be resolved — backport an upstream\npatch, rebase to a newer version, or mark it as not-affected. A wrong call here\ninvalidates everything downstream, which is why it's the natural starting point\nfor a model benchmark.</p><p>The 4.6 models ran with <code>REASONING_EFFORT=high</code>, which enables native extended\nthinking. Opus 4.8 ran without it — a LiteLLM/BeeAI provider ID mismatch caused\nthe model to reject the thinking parameter, so we disabled it entirely\n(<a href=\"https://github.com/i-am-bee/beeai-framework/issues/1463\" target=\"_blank\" rel=\"noopener noreferrer\">tracked here</a>). The harness runs all five issues concurrently and captures per-issue\nmetrics from the agent framework: wall-clock duration, tool call count, and\ntotal token usage.</p><p>This is the first time we've done this kind of work and it was quite a learning\nexperience. This blog post contains data from a single run with each model.</p><p>I already have ideas for improvement for a future run. We need to extend the\nscope to backporting agent as well and have at least ten cases. Doing multiple\nruns per model with aggregation would also give us more grounded results.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"analysis\">Analysis<a href=\"#analysis\" class=\"hash-link\" aria-label=\"Direct link to Analysis\" title=\"Direct link to Analysis\">​</a></h2><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"resolutions\">Resolutions<a href=\"#resolutions\" class=\"hash-link\" aria-label=\"Direct link to Resolutions\" title=\"Direct link to Resolutions\">​</a></h3><p>All three models reached identical conclusions on all five issues. The triage\ndecisions were unambiguous: three backports (RHEL-15216, RHEL-112546,\nRHEL-177992) and two not-affected (RHEL-114607, RHEL-174694). RHEL-114607 is\nworth highlighting — the issue concerns CVE-2025-59375 in expat, which only\naffects versions before 2.7.2. RHEL 10 already ships 2.7.3, so the models\ncorrectly concluded not-affected rather than recommending a rebase to 2.7.5.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"speed\">Speed<a href=\"#speed\" class=\"hash-link\" aria-label=\"Direct link to Speed\" title=\"Direct link to Speed\">​</a></h3><p>Sonnet 4.6 was the fastest model on four of the five issues, sometimes by a\nlarge margin. RHEL-112546 illustrates the biggest spread: Sonnet resolved it in\n98s with just 9 tool calls, while Opus 4.6 took 267s and 37 tool calls, and\nOpus 4.8 took 154s and 25 tool calls. Both Opus models invested significantly\nmore effort on this libtiff CVE, exploring more patch URLs and performing\ndeeper code analysis.</p><p>RHEL-174694 shows the opposite pattern: Opus 4.8 took 389s with 17 tool calls —\nmore than twice Sonnet's 167s — despite using fewer tool calls. The extended\nthinking budget appeared to cause the model to deliberate at length before\nsettling on a conclusion that Sonnet reached more directly.</p><p>Opus 4.8 is consistently faster than Opus 4.6 (except for RHEL-174694), which\nsuggests the architecture improvements between the two generations translate\ninto more efficient reasoning chains.</p><p>The stark difference between the numbers is not just caused by the model\nevolution but also the fact how non-deterministic task this triage is. We are\nalso not utilizing Opus 4.8's adaptive thinking.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"token-usage-and-cost\">Token usage and cost<a href=\"#token-usage-and-cost\" class=\"hash-link\" aria-label=\"Direct link to Token usage and cost\" title=\"Direct link to Token usage and cost\">​</a></h3><p>The token numbers reveal a notable pattern: Opus 4.8 uses more input tokens\nthan Opus 4.6 for the same issues, but far fewer output tokens. On\nRHEL-112546, Opus 4.6 produced 11,268 output tokens versus Opus 4.8's 5,864\n— the newer model reasons more concisely even when it reads more context.</p><p>Cost differences are significant but concrete numbers highly depend on the\nactual plan.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"takeaway\">Takeaway<a href=\"#takeaway\" class=\"hash-link\" aria-label=\"Direct link to Takeaway\" title=\"Direct link to Takeaway\">​</a></h3><p>For the triage workload we tested, Sonnet 4.6 offers the best price-performance\nratio by a wide margin. Opus models invested more in investigation on hard\nissues but did not produce different conclusions. Opus 4.8's speed advantage\nover Opus 4.6 is real but does not close the cost gap.</p><p>On the other hand, this is an evaluation harness, so we need to make a real\njudgement in our day to day work while processing real issues.</p><p>None of this analysis would be possible without the incredible work of the\nwhole team and especially <a href=\"https://github.com/TomasKorbar\" target=\"_blank\" rel=\"noopener noreferrer\">Tomas Korbar</a> who\nauthored the E2E test suite, <a href=\"https://github.com/opohorel\" target=\"_blank\" rel=\"noopener noreferrer\">Ondrej Pohorelsky</a>\nwho contributed the initial support for Opus 4.8 to\n<a href=\"https://github.com/packit/ai-workflows\" target=\"_blank\" rel=\"noopener noreferrer\">ai-workflows</a>, <a href=\"https://github.com/nforro\" target=\"_blank\" rel=\"noopener noreferrer\">Nikola\nForro</a> - author of our minimal trace-server, <a href=\"https://github.com/lbarcziova\" target=\"_blank\" rel=\"noopener noreferrer\">Laura\nBarcziova</a> whose scripts and Claude skills I\nused for this research, <a href=\"https://github.com/mfocko\" target=\"_blank\" rel=\"noopener noreferrer\">Matej Focko</a> for consulting\nwith me all the time, and <a href=\"https://github.com/majamassarini\" target=\"_blank\" rel=\"noopener noreferrer\">Maja Massarini</a>\nfor the polished Makefile &amp; compose setup that carried the test runs.</p>",
            "url": "https://packit.dev/posts/comparing-frontier-models-june2026",
            "title": "Comparing frontier Claude models for our AI workflows (June 2026)",
            "summary": "We evaluated three Claude frontier models: Sonnet 4.6, Opus 4.6, and Opus 4.8.",
            "date_modified": "2026-06-09T11:51:53.000Z",
            "author": {
                "name": "Tomáš Tomeček",
                "url": "https://github.com/TomasTomecek"
            },
            "tags": [
                "AI",
                "automation",
                "development",
                "eval"
            ]
        },
        {
            "id": "https://packit.dev/posts/multiple-release-streams",
            "content_html": "<p>There are upstream projects that have multiple release streams and, for example, regularly release\npatch versions for every active minor version. With\n<a href=\"/docs/configuration/downstream/pull_from_upstream\"><code>pull-from-upstream</code></a> you have been able\nto follow only the highest stream, but that now changes. By switching\n<a href=\"https://the-new-hotness.readthedocs.io/en/stable/user-guide.html#notifications-settings-legacy\" target=\"_blank\" rel=\"noopener noreferrer\"><code>Monitoring status</code></a>\nof your package from <code>Monitoring</code> to <code>Monitoring all</code>, you enable triggering\n<a href=\"/docs/configuration/downstream/pull_from_upstream\"><code>pull-from-upstream</code></a>\nfor every released version, not only the highest. This means you can use options such as\n<a href=\"/docs/configuration#version_update_mask\"><code>version_update_mask</code></a>,\n<a href=\"/docs/configuration#upstream_tag_include\"><code>upstream_tag_include</code></a> or\n<a href=\"/docs/configuration#upstream_tag_exclude\"><code>upstream_tag_exclude</code></a> (those require\n<a href=\"/docs/configuration#upstream_project_url\"><code>upstream_project_url</code></a> to be set)\nto filter a specific release stream you want to follow, or have multiple\n<a href=\"/docs/configuration/downstream/pull_from_upstream\"><code>pull-from-upstream</code></a> jobs,\neach matching different releases and targeting different dist-git branches.</p><div class=\"theme-admonition theme-admonition-tip alert alert--success admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_S0QG\"><p>Instead of changing <code>Monitoring status</code> in the dist-git web UI, you can have a\n<a href=\"https://the-new-hotness.readthedocs.io/en/stable/user-guide.html#notifications-settings\" target=\"_blank\" rel=\"noopener noreferrer\"><code>monitoring.toml</code></a>\nfile in the <code>rawhide</code> branch in dist-git and set <code>all_versions = true</code> to trigger\n<a href=\"/docs/configuration/downstream/pull_from_upstream\"><code>pull-from-upstream</code></a> for all released versions.</p></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"configuration-example\">Configuration example<a href=\"#configuration-example\" class=\"hash-link\" aria-label=\"Direct link to Configuration example\" title=\"Direct link to Configuration example\">​</a></h2><p>For an upstream project releasing 1.7.z and 1.6.z streams, you could configure the jobs like this:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">jobs:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- job: pull_from_upstream</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  trigger: release</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  upstream_tag_exclude: ^v1\\.6\\.\\d+$</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  dist_git_branches:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">   - fedora-rawhide</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- job: pull_from_upstream</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  trigger: release</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  upstream_tag_include: ^v1\\.6\\.\\d+$</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  dist_git_branches:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">   - fedora-branched</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>With this configuration security backports to the 1.6 upstream branch would result in Packit opening dist-git PRs\nagainst branched Fedoras while for any other release Packit would open dist-git PRs in Rawhide.</p><div class=\"theme-admonition theme-admonition-tip alert alert--success admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_S0QG\"><p>We have introduced a new configuration option\n<a href=\"/docs/configuration#version_update_specifiers\"><code>version_update_specifiers</code></a>.\nIt borrows syntax of\n<a href=\"https://peps.python.org/pep-0440/#version-specifiers\" target=\"_blank\" rel=\"noopener noreferrer\">PEP440 version specifiers</a>\nand gives you more flexibility when filtering release streams. For example:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">jobs:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- job: pull_from_upstream</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  trigger: release</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  # 3.y.z or higher versions go to Rawhide</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  version_update_specifiers: &gt;=3.0</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  dist_git_branches:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">   - fedora-rawhide</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- job: pull_from_upstream</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  trigger: release</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  # versions 2.y.z go to stable Fedoras, excluding a known broken version</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  version_update_specifiers: ~=2.0, !=2.5.4</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  dist_git_branches:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">   - fedora-branched</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div></div></div>",
            "url": "https://packit.dev/posts/multiple-release-streams",
            "title": "Packit now supports multiple release streams",
            "summary": "There are upstream projects that have multiple release streams and, for example, regularly release",
            "date_modified": "2026-04-08T08:00:00.000Z",
            "author": {
                "name": "Nikola Forró",
                "url": "https://github.com/nforro"
            },
            "tags": [
                "Upstream Release Monitoring",
                "pull-from-upstream",
                "downstream",
                "configuration"
            ]
        },
        {
            "id": "https://packit.dev/posts/forgejo-in-ogr",
            "content_html": "<p>We are happy to announce that the ogr library now supports yet another open-source git forge — <a href=\"https://forgejo.org/\" target=\"_blank\" rel=\"noopener noreferrer\">Forgejo</a>. This brings the total number of supported forges to four. Thank you to all external contributors and especially <a href=\"https://github.com/mynk8\" target=\"_blank\" rel=\"noopener noreferrer\">mynk8</a> who helped to turn this part of the project into reality!</p><h1>What is ogr?</h1><p><a href=\"https://github.com/packit/ogr\" target=\"_blank\" rel=\"noopener noreferrer\">Ogr</a> stands for <strong>One Git library to Rule</strong>. It is a library offering a unified API for multiple git forges, meaning that it makes it possible to communicate with all supported git forges using the same set of methods. Historically, the list of supported forges consisted of <strong>GitHub</strong>, <strong>GitLab</strong> and <strong>Pagure</strong>. This list has now been expanded to include <strong>Forgejo</strong> as well.</p><p>Here is a short example showcasing how to create a new issue in a repository using ogr:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">from ogr import ForgejoService</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">service = ForgejoService(instance_url=\"https://codeberg.org\", token=\"...\")</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">project = service.get_project(namespace=\"owner\", repo=\"repo\")</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">project.create_issue(title=\"Issue title\", body=\"Issue description\")</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>For more information see our <a href=\"https://packit.github.io/ogr/\" target=\"_blank\" rel=\"noopener noreferrer\">documentation</a> and <a href=\"https://github.com/packit/ogr/tree/main/examples\" target=\"_blank\" rel=\"noopener noreferrer\">Jupyter notebook examples</a>.</p><h1>What this means for Packit</h1><p>With the added support of Forgejo in ogr, it is now possible for us to work on support of Forgejo as dist-git in Packit. If interested, you can track our progress on the upcoming addition in <a href=\"https://github.com/packit/packit-service/issues/2861\" target=\"_blank\" rel=\"noopener noreferrer\">this epic</a>.</p>",
            "url": "https://packit.dev/posts/forgejo-in-ogr",
            "title": "Forgejo is now supported in ogr",
            "summary": "We are happy to announce that the ogr library now supports yet another open-source git forge — Forgejo. This brings the total number of supported forges to four. Thank you to all external contributors and especially mynk8 who helped to turn this part of the project into reality!",
            "date_modified": "2026-02-10T13:00:00.000Z",
            "author": {
                "name": "Alžběta Kučerová",
                "url": "https://github.com/betulependule"
            },
            "tags": [
                "Forgejo",
                "ogr"
            ]
        },
        {
            "id": "https://packit.dev/posts/lessons-learned-ai-automation-rhel",
            "content_html": "<p>After building and running AI-powered automation for RHEL package maintenance workflows (available in <a href=\"https://github.com/packit/ai-workflows\" target=\"_blank\" rel=\"noopener noreferrer\">this</a> repo), our team has learned a lot about what it takes to move from impressive demos to a reliable production system. Here are the key insights that might save you time and frustration on your own AI automation journey.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"too-many-frameworks\">Too many frameworks<a href=\"#too-many-frameworks\" class=\"hash-link\" aria-label=\"Direct link to Too many frameworks\" title=\"Direct link to Too many frameworks\">​</a></h2><p>When we started this project, the number of AI frameworks available was both exciting and overwhelming. We experimented with multiple approaches:</p><ul><li><strong><a href=\"https://block.github.io/goose/\" target=\"_blank\" rel=\"noopener noreferrer\">Goose AI</a></strong> - Our early experiments used Goose with YAML-based recipes for tasks like issue triage and package rebasing</li><li><strong><a href=\"https://framework.beeai.dev\" target=\"_blank\" rel=\"noopener noreferrer\">BeeAI Framework</a></strong> - Eventually became our production choice, offering more structured agent development with requirement-based workflows involving a lot of code automation (Python-based)</li><li><strong><a href=\"https://google.github.io/adk-docs/get-started/quickstart\" target=\"_blank\" rel=\"noopener noreferrer\">Google's ADK</a></strong> - A big contender, it took us hours to debate and decide</li><li><strong><a href=\"https://llamastack.github.io/latest/\" target=\"_blank\" rel=\"noopener noreferrer\">LlamaStack</a></strong> - It wasn't mature enough</li><li><strong>Custom MCP (Model Context Protocol)</strong> integrations - For connecting to services like Jira and GitLab</li></ul><p>The reality? Every framework has trade-offs, and the “best” choice depends heavily on your specific use case. Goose was great for rapid prototyping and was an excellent starting point choice, but we quickly discovered we needed something more robust for production. With so many options available, we went with something we were able to easily start with and still achieve good results. BeeAI's structured approach with conditional requirements and many more possibilities of restrictions and control over agents proved more suitable for our complex, multi-step workflows.</p><p>Since security is very important for the production-level system, and it's also easy to create your own MCP server, we've opted for that option so the code is 100% controlled by us. This way, we can define exactly which Jira fields can be touched, what values are allowed, and under what conditions. Agents get an exact list of functions they can use, and none of them have any credentials in their environment: everything that needs authentication goes through MCP.</p><p><strong>Lesson learned:</strong> Don't get stuck in analysis paralysis. Pick a framework that aligns with your team's expertise and iterate. You can always migrate later (and we did).</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"the-demo-to-production-gap-is-enormous\">The Demo-to-Production gap is enormous<a href=\"#the-demo-to-production-gap-is-enormous\" class=\"hash-link\" aria-label=\"Direct link to The Demo-to-Production gap is enormous\" title=\"Direct link to The Demo-to-Production gap is enormous\">​</a></h2><p>AI agents can be incredibly impressive in demos. Show someone an agent that can analyse a Jira issue, determine it needs a backport, find the upstream patch, and apply it automatically - and they'll be amazed. As we were amazed too. But making that work reliably in production? That's where the real work begins.</p><p>Our triage agent, which analyses Jira issues and decides follow-up actions, for example, has a 150+ line prompt with detailed decision trees:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># From Triage Agent - just a snippet of the complexity</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">\"\"\"</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">**Decision Guidelines &amp; Investigation Steps**</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"display:inline-block;color:#e3116c\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">You must decide between one of 5 actions. Follow these guidelines:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"display:inline-block;color:#e3116c\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">1. **Rebase** - Only when issue explicitly instructs to \"rebase\" or \"update\"</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">2. **Backport a Patch OR Request Clarification**</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">   2.1. Deep Analysis of the Issue</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">   2.2. Systematic Source Investigation</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">   2.3. Validate the Fix and URL</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">   2.4. Decide the Outcome</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">3. **No Action** - For non-bugs (QE tasks, features, docs)</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">4. **Error** - Processing issues preventing analysis</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">\"\"\"</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>What looks like a simple “analyse this issue” task actually requires:</p><ul><li>Complex decision trees with multiple fallback paths</li><li>Comprehensive error handling for edge cases</li><li>Detailed validation of patches and URLs</li><li>Integration with multiple external systems (Jira, GitLab, upstream repos)</li></ul><p><strong>Lesson learned:</strong> Don't let demo success fool you into underestimating production complexity.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"the-art-of-decomposition\">The art of decomposition<a href=\"#the-art-of-decomposition\" class=\"hash-link\" aria-label=\"Direct link to The art of decomposition\" title=\"Direct link to The art of decomposition\">​</a></h2><p>Like many AI projects, we started with the foolish idea of building one super-agent that could handle everything. Fortunately, we realised very quickly that this just isn't possible - at least not reliably.</p><p>Our foundation became three core agents, which proved to be an excellent starting point:</p><ol><li><strong>Triage Agent</strong> - Analyses Jira issues and determines the resolution path</li><li><strong>Rebase Agent</strong> - Handles package updates to newer upstream versions</li><li><strong>Backport Agent</strong> - Applies specific patches and fixes</li></ol><p>But as we started encountering specific production issues and as these agents grew increasingly complex with corner cases and real-world requirements, we began implementing even more specialised agents that integrate seamlessly with our main three.</p><p>The Log Agent is a perfect example of this evolution. Instead of having the backport and rebase agents figure out how to document their changes (adding yet another responsibility to already complex workflows), we created a dedicated specialist:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># This is just a snippet from the Log Agent instructions</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">\"\"\"</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">You are an expert on summarizing packaging changes in RHEL ecosystem.</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">To document a change:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">1. Use `git diff --cached` to see the final changes staged for commit</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">2. Add a changelog entry to the spec file with proper formatting</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">3. Generate a commit message title (max 80 characters)</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">4. Summarize changes for the merge request description</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token triple-quoted-string string\" style=\"color:#e3116c\">\"\"\"</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>This specialisation journey is still ongoing, and we can absolutely see opportunities to create even smaller, more focused agents. Each new specialised agent makes our workflows more robust and our main agents cleaner and more reliable.</p><p><strong>Lesson learned:</strong> Start with a small number of core agents, but don't be afraid to extract specialised functionality as complexity grows.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"models-matter-but-tooling-and-architecture-matter-more\">Models matter, but tooling and architecture matter more<a href=\"#models-matter-but-tooling-and-architecture-matter-more\" class=\"hash-link\" aria-label=\"Direct link to Models matter, but tooling and architecture matter more\" title=\"Direct link to Models matter, but tooling and architecture matter more\">​</a></h2><p>We've experimented with multiple models, providers and settings:</p><ul><li><a href=\"https://ai.google.dev/gemini-api\" target=\"_blank\" rel=\"noopener noreferrer\">Google's Gemini</a> (currently <code>gemini-2.5-pro</code>)</li><li><a href=\"https://claude.ai/\" target=\"_blank\" rel=\"noopener noreferrer\">Anthropic's Claude</a> (<code>claude-sonnet-4</code>)</li><li>Custom temperature and parameter tuning</li></ul><p>Yes, newer models often perform better, and it's worth trying them. But here's what matters more:</p><ol><li><strong>Proper tooling:</strong> Our agents have access to specialised tools, which provide deterministic, reliable functionality that the AI can leverage.</li><li><strong>Task decomposition:</strong> Breaking complex workflows into smaller, manageable steps with clear inputs and outputs.</li><li><strong>Validation and error handling:</strong> Every step has validation, and failures are handled gracefully with retry logic.</li><li><strong>Explicit system prompt:</strong> LLMs can be very creative in their solutions, make sure to precisely guide them via system prompts.</li></ol><p>For example, our backport agent doesn't just “apply a patch” - it has a sophisticated workflow and tools:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># Specialized tools for reliable patch handling</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">tools</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    GitPatchCreationTool</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">options</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">local_tool_options</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    GitPatchApplyTool</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">options</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">local_tool_options</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    GitPatchApplyFinishTool</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">options</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">local_tool_options</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    GitLogSearchTool</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">options</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">local_tool_options</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    GitPreparePackageSourcesTool</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">options</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">local_tool_options</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ... more specialized tools</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p><strong>Lesson learned:</strong> Invest time in tooling and architecture.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"mixing-ai-creativity-with-code-reliability\">Mixing AI creativity with code reliability<a href=\"#mixing-ai-creativity-with-code-reliability\" class=\"hash-link\" aria-label=\"Direct link to Mixing AI creativity with code reliability\" title=\"Direct link to Mixing AI creativity with code reliability\">​</a></h2><p>This might be the most important lesson: AI agents will never be 100% deterministic, and that's actually okay for many use cases. But you need to be strategic about where you accept non-determinism and where you demand consistency.</p><p><strong>Examples where we embrace AI non-determinism:</strong></p><ul><li>Analysing natural language in Jira issues</li><li>Writing commit messages and documentation</li><li>Searching for fixes upstream</li></ul><p><strong>Examples where we use deterministic code:</strong></p><ul><li>Git operations (clone, checkout, apply patches)</li><li>File system operations</li><li>Complex deterministic logic, like mapping RHEL versions to branches</li></ul><p><strong>Lesson learned:</strong> Design your system to be “AI-assisted” rather than “AI-controlled”. Use AI for the creative, analytical work, but rely on deterministic code for the critical operations.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"from-code-to-service\">From code to service<a href=\"#from-code-to-service\" class=\"hash-link\" aria-label=\"Direct link to From code to service\" title=\"Direct link to From code to service\">​</a></h2><p>Once you move from building a prototype to building a production system, you also need to think about the infrastructure and other components, not just agents and code around them. Here are just a few examples of what we architected that keeps AI agents running reliably:</p><ul><li><strong>Queue-based architecture:</strong> We use valkey queues to orchestrate work between agents, a reliable pattern we already knew worked. Issues flow through different queues with automatic retry logic.</li><li><strong>Observability:</strong> Every agent action flows through <a href=\"https://phoenix.arize.ai/\" target=\"_blank\" rel=\"noopener noreferrer\">Phoenix tracing</a>, giving us complete visibility into what agents are thinking and doing. When something goes wrong, we can trace exactly which decisions led to the failure. This isn't just logging - it's understanding why your AI system made specific choices.</li><li><strong>Container deployment:</strong> The entire system runs on OpenShift and each agent type has its own deployment with resource limits. This also makes the whole system easily scalable.</li><li><strong>Dry-run capabilities:</strong> Every operation has a dry-run support built in. This helps us to better test and debug the agent's behaviour. When an agent makes an unexpected decision, we can replay the scenario safely.</li></ul><p><strong>Lesson learned:</strong> Start thinking about operational capabilities on day one. Dry-run modes, proper logging, and failure recovery aren't “nice to haves” - they are what makes AI systems actually usable. And since LLMs produce a ton of output, you'll need an efficient way to find out why the agents made such an odd decision.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"takeaways\">Takeaways<a href=\"#takeaways\" class=\"hash-link\" aria-label=\"Direct link to Takeaways\" title=\"Direct link to Takeaways\">​</a></h2><p>After roughly 3.5 months of development, our system is currently running for a selected set of components - and it's being heavily developed. But by following these principles, we've seen a huge difference in reliability and maintainability. More importantly, we're now much clearer about what's actually possible to do with AI and what isn't.</p><p>Ask me again in 3 months, and I'll probably have another set of valuable lessons learned. But that's the nature of this rapidly evolving field.</p>",
            "url": "https://packit.dev/posts/lessons-learned-ai-automation-rhel",
            "title": "Lessons learned: Building production AI automation for RHEL package maintenance",
            "summary": "After building and running AI-powered automation for RHEL package maintenance workflows (available in this repo), our team has learned a lot about what it takes to move from impressive demos to a reliable production system. Here are the key insights that might save you time and frustration on your own AI automation journey.",
            "date_modified": "2025-10-05T23:00:00.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "AI",
                "automation",
                "RHEL"
            ]
        },
        {
            "id": "https://packit.dev/posts/specfile-advanced",
            "content_html": "<p>Are you already familiar with the basic concepts of the <em>specfile</em> library?\nThen welcome to a collection of some slightly more advanced topics that you could find useful.\nIf you're not that familiar and would like to start with something easier,\nyou can take a look at <a href=\"/posts/specfile-introduction\">Introduction to specfile library</a>.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"forced-parsing\">Forced parsing<a href=\"#forced-parsing\" class=\"hash-link\" aria-label=\"Direct link to Forced parsing\" title=\"Direct link to Forced parsing\">​</a></h2><p>Imagine you want to make changes to a spec file that requires some sources\nto be present at the time of parsing such as sources referenced from shell\nexpansions (e.g. <code>%(date +%F -r %{SOURCE0})</code>), includes some external files\nusing the <code>%include</code> directive, or loads external macrofiles with the <code>%load</code> macro,\nbut all you have is the spec file itself.</p><p>In such case you may want to instantiate <code>Specfile</code> with the <code>force_parse</code> argument\nset to <code>True</code> in order to attempt to parse the spec file with missing external files.\nIf that succeeds and some required external files were indeed missing during parsing,\nthe <code>Specfile.tainted</code> property is set to <code>True</code> to indicate that certain assumptions\ncould be broken - for example a condition that relies on a macro defined in an external\nmacrofile could be evaluated incorrectly.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"defining-and-undefining-macros\">Defining and undefining macros<a href=\"#defining-and-undefining-macros\" class=\"hash-link\" aria-label=\"Direct link to Defining and undefining macros\" title=\"Direct link to Defining and undefining macros\">​</a></h2><p>You can define or undefine any RPM macros before parsing a spec file with the <code>macros</code>\nargument to the <code>Specfile</code> constructor. The argument takes a list of 2-string tuples\nwhere the first element is macro name and the second element is macro value.\nIf the second element is <code>None</code>, the macro will be undefined. This can come in handy\nwhen you need to undefine a system macro such as <code>fedora</code>.</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">from</span><span class=\"token plain\"> specfile </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> Specfile</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    macros</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"fedora\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">None</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"epel\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"9\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>It is also possible to pass macro definitions in the same format as the <code>extra_macros</code>\nargument to the <code>Specfile.expand()</code> method in order to temporarily define or undefine macros\nbefore expression expansion.</p><p>For example, the following code snippet will print the expanded value of the <code>Release</code> tag\nwithout system dist tag:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">print</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">expand</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"%release\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> extra_macros</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"dist\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">None</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><div class=\"theme-admonition theme-admonition-note alert alert--secondary admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z\"></path></svg></span>note</div><div class=\"admonitionContent_S0QG\"><p>This is just for demonstration of <code>extra_macros</code>, you can achieve the same with:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">print</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">expanded_release</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"conditions-and-expansion\">Conditions and expansion<a href=\"#conditions-and-expansion\" class=\"hash-link\" aria-label=\"Direct link to Conditions and expansion\" title=\"Direct link to Conditions and expansion\">​</a></h2><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"validity\">Validity<a href=\"#validity\" class=\"hash-link\" aria-label=\"Direct link to Validity\" title=\"Direct link to Validity\">​</a></h3><p><code>MacroDefinition</code>, <code>Tag</code>, <code>SourceListEntry</code>, <code>Source</code> and <code>Patch</code> classes have a <code>valid</code> attribute\nthat determines if the respective entity is in a true branch of a condition (provided that the condition\nis not present in a false branch of another condition).</p><p>Having the following in a spec file:</p><div class=\"language-specfile codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-specfile codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%if %{defined copr_username}</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Epoch: 102</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%else</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Epoch: 2</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%endif</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>You can use the <code>Tag.valid</code> attribute to choose the suitable <code>Epoch</code> tag based on validity:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">from</span><span class=\"token plain\"> specfile </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> Specfile</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">tags</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> tags</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    epoch_tags </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">t </span><span class=\"token keyword\" style=\"color:#00009f\">for</span><span class=\"token plain\"> t </span><span class=\"token keyword\" style=\"color:#00009f\">in</span><span class=\"token plain\"> tags </span><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> t</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">normalized_name </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Epoch\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># print the value of the first Epoch tag, disregarding the condition</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">print</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">epoch_tags</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token number\" style=\"color:#36acaa\">0</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">value</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># print the value of the first valid Epoch tag</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">print</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token builtin\">next</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">t </span><span class=\"token keyword\" style=\"color:#00009f\">for</span><span class=\"token plain\"> t </span><span class=\"token keyword\" style=\"color:#00009f\">in</span><span class=\"token plain\"> epoch_tags </span><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> t</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">valid</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">value</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># when accessing tags by name the first valid one is chosen,</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># so this does the same as above</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">print</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">tags</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">epoch</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">value</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"expression-expansion\">Expression expansion<a href=\"#expression-expansion\" class=\"hash-link\" aria-label=\"Direct link to Expression expansion\" title=\"Direct link to Expression expansion\">​</a></h3><p>You can get expanded values of tags with their <code>expanded_value</code> property. This is the literal\nvalue of a tag as present in the spec file that is passed to <code>Specfile.expand()</code> for expansion.</p><p>If you are not interested in modification and want to get exactly what <code>rpmspec --parse example.spec</code>\nwould give you, you can use the <code>Specfile.parsed_sections</code> property:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">tags</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">parsed_sections</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">package</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> tags</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">print</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">tags</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">value</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>Doing this means that all conditions and macros will be already expanded, so all tags will be valid\nand their <code>value</code> and <code>expanded_value</code> will be the same. Modifications will have no effect.</p><p>You can also access the underlying <code>rpm.spec</code> object with the <code>Specfile.rpm_spec</code> property,\nwhich allows you to do things like:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">print</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">rpm_spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">sourceHeader</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">epoch</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>In this case the printed value will be a number, not a string like in previous cases.</p><div class=\"theme-admonition theme-admonition-info alert alert--info admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z\"></path></svg></span>info</div><div class=\"admonitionContent_S0QG\"><p>This means you have 3 ways how to get expanded value of a tag with the <em>specfile</em> library.\nAll of them should give you same or very similar results, but only the first one gives you access\nalso to the unexpanded value of a tag and the possibility to modify it. On the other hand it will\nalso take the most time, so think twice if performance is a concern.</p></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"making-modifications-less-obstructive\">Making modifications less obstructive<a href=\"#making-modifications-less-obstructive\" class=\"hash-link\" aria-label=\"Direct link to Making modifications less obstructive\" title=\"Direct link to Making modifications less obstructive\">​</a></h2><p>Consider the following in a spec file:</p><div class=\"language-specfile codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-specfile codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">#global rc_ver 3</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global maj_ver 12</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global min_ver 0</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global patch_ver 1</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Name:       %{pkg_name}</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Version:    %{maj_ver}.%{min_ver}.%{patch_ver}%{?rc_ver:~rc%{rc_ver}}</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>Rather than replacing the value of <code>Version</code> with a version string, removing all the macro\nsubstitutions in the process, you can use <code>Specfile.update_tag()</code> and have it try to update\nthe relevant macro definitions instead:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">from</span><span class=\"token plain\"> specfile </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> Specfile</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">update_tag</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"Version\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"12.1.0\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>This will result in:</p><div class=\"language-specfile codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-specfile codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">#global rc_ver 3</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global maj_ver 12</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global min_ver 1</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global patch_ver 0</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Name:       %{pkg_name}</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Version:    %{maj_ver}.%{min_ver}.%{patch_ver}%{?rc_ver:~rc%{rc_ver}}</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>It will even uncomment a commented-out macro definition if needed:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">update_tag</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"Version\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"12.1.1~rc1\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>This will result in:</p><div class=\"language-specfile codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-specfile codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global rc_ver 1</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global maj_ver 12</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global min_ver 1</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global patch_ver 1</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Name:       %{pkg_name}</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Version:    %{maj_ver}.%{min_ver}.%{patch_ver}%{?rc_ver:~rc%{rc_ver}}</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>However, if you want to go back to a regular version, you have to comment out the relevant\nmacro definition explicitly:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">from</span><span class=\"token plain\"> specfile </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> Specfile</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">from</span><span class=\"token plain\"> specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">macro_definitions </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> CommentOutStyle</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">macro_definitions</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> macro_definitions</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># use the original comment-out style</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    macro_definitions</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">rc_ver</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">comment_out_style </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> CommentOutStyle</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">HASH</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    macro_definitions</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">rc_ver</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">commented_out </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">True</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">update_tag</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"Version\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"12.1.1\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>This will result in:</p><div class=\"language-specfile codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-specfile codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">#global rc_ver 1</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global maj_ver 12</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global min_ver 1</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">%global patch_ver 1</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Name:       %{pkg_name}</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Version:    %{maj_ver}.%{min_ver}.%{patch_ver}%{?rc_ver:~rc%{rc_ver}}</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>The algorithm isn't perfect and won't work in all situations, but even if it's not possible to update\nsome macro definitions it is guaranteed that <code>expanded_value</code> of a tag after calling <code>update_tag()</code>\nwill be equal to the given value.</p><p>There is also a more general method <code>Specfile.update_value()</code> that allows you to update any string\nwithin a spec file in the same manner, trying to preserve macro substitutions and update relevant\nmacro definitions (or even tag values in case of e.g. <code>%{version}</code>) if possible. It is up to you\nto replace the original string with the result (that can but doesn't have to be exactly the same).</p><div class=\"theme-admonition theme-admonition-info alert alert--info admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z\"></path></svg></span>info</div><div class=\"admonitionContent_S0QG\"><p>The algorithm first tokenizes the string to be updated. Then it determines which macro substitutions\nwithin the string can be affected by modifying bodies of preceding macro definitions or values\nof preceding tags. Then it identifies substrings that are deemed modifiable (that could be for example\na sequence of numbers between two dots) and constructs a regular expression in which the modifiable\nmacro substitutions and the modifiable substrings are capturing groups.\nIf the requested new string is a not match to this regular expression, nothing happens and the requested\nnew string is returned unchanged. If it is a match though, the captured groups corresponding to modifiable\nmacro substitutions are processed, recursively, starting with tokenization once again. The requested\nnew string is then updated with corresponding macro substitutions from the original string and returned.</p></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"more-info-and-links\">More info and links<a href=\"#more-info-and-links\" class=\"hash-link\" aria-label=\"Direct link to More info and links\" title=\"Direct link to More info and links\">​</a></h2><p>Are you interested in more details, trying the library out or even contributing?\nYou can find <em>specfile</em> source code on <a href=\"https://github.com/packit/specfile\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub</a>.\nSee the <a href=\"https://github.com/packit/specfile/blob/main/README.md\" target=\"_blank\" rel=\"noopener noreferrer\">README</a> for more tips and usage examples.\nYou can also check out the <a href=\"https://packit.dev/specfile/api/specfile\" target=\"_blank\" rel=\"noopener noreferrer\">API reference</a>.</p>",
            "url": "https://packit.dev/posts/specfile-advanced",
            "title": "Advanced usage of the specfile library",
            "summary": "Are you already familiar with the basic concepts of the specfile library?",
            "date_modified": "2025-01-09T00:00:00.000Z",
            "author": {
                "name": "Nikola Forró",
                "url": "https://github.com/nforro"
            },
            "tags": [
                "specfile"
            ]
        },
        {
            "id": "https://packit.dev/posts/packit-in-2024",
            "content_html": "<p>We are reaching the end of the year and it’s a good time to look back at the Packit highlights of this year. And it was a year!</p><p>We didn’t take a winter sleep, and at the very start of the year, we <a href=\"https://packit.dev/posts/specfile-introduction\" target=\"_blank\" rel=\"noopener noreferrer\">announced</a> the <a href=\"https://github.com/packit/specfile\" target=\"_blank\" rel=\"noopener noreferrer\">Python library for parsing specfiles</a>. (Mainly written by <a href=\"https://github.com/nforro\" target=\"_blank\" rel=\"noopener noreferrer\">Nikola</a>.) We had been successfully using it for some time and it was time to give the benefit to others. Thanks to that, there is now a <a href=\"https://github.com/dcermak/rpm-spec-language-server\" target=\"_blank\" rel=\"noopener noreferrer\">language Server for RPM spec files</a>.</p><p>A lot usually happens in Brussels at the turn of January and February. And this time, we were present as well for the first time. <a href=\"https://mastodonczech.cz/@lachmanfrantisek\" target=\"_blank\" rel=\"noopener noreferrer\">František</a> (joined by <a href=\"https://github.com/ukulekek\" target=\"_blank\" rel=\"noopener noreferrer\">Evgeny</a>) presented on <a href=\"https://www.youtube.com/watch?v=Eqb6IqG7Jek\" target=\"_blank\" rel=\"noopener noreferrer\">CentOS Connect how Packit and Testing Farm can be beneficial to the CentOS community</a>. Also, at this conference, there was a meetup of the <a href=\"https://sigs.centos.org/integration/\" target=\"_blank\" rel=\"noopener noreferrer\">CentOS Integration SIG</a> which <a href=\"https://fosstodon.org/@m4tt_314\" target=\"_blank\" rel=\"noopener noreferrer\">Matej</a> and <a href=\"https://mastodonczech.cz/@lachmanfrantisek\" target=\"_blank\" rel=\"noopener noreferrer\">František</a> joined. The main event in Brussels is the <a href=\"https://fosdem.org/2024/\" target=\"_blank\" rel=\"noopener noreferrer\">FOSDEM conference</a>, a big conference consisting of multiple so-called rooms. <a href=\"https://mastodonczech.cz/@lachmanfrantisek\" target=\"_blank\" rel=\"noopener noreferrer\">František</a> took <a href=\"https://fosdem.org/2024/schedule/event/fosdem-2024-2881-upstream-and-downstream-best-friends-forever-/\" target=\"_blank\" rel=\"noopener noreferrer\">an interactive session</a> in the Distribution room about the relationship between upstream and downstream.</p><p>During the whole year, we have made many improvements so more packages can use Packit’s Fedora release automation. Since many packages can benefit from Packit right away, we’ve introduced an <a href=\"https://packit.dev/docs/cli/dist-git/init\" target=\"_blank\" rel=\"noopener noreferrer\">onboarding command</a> capable of preparing a configuration file and also moving it to dist-git – either via pull requests or direct push.</p><p>For some time, Packit has been able to build VM images thanks to the prototype integration with the <a href=\"https://console.redhat.com/insights/image-builder\" target=\"_blank\" rel=\"noopener noreferrer\">Image Builder service</a>. To promote this functionality and see if there is enough demand to continue development, <a href=\"https://github.com/majamassarini\" target=\"_blank\" rel=\"noopener noreferrer\">Maja</a> prepared a <a href=\"https://developers.redhat.com/articles/2024/04/02/customize-aws-cloud-images-rhel-image-builder-and-packit#\" target=\"_blank\" rel=\"noopener noreferrer\">blog post</a> for RedHat’s Developer Portal (also <a href=\"https://packit.dev/posts/aws-and-image-builder\" target=\"_blank\" rel=\"noopener noreferrer\">available</a> on Packit’s webpage).</p><p>As each year, the team met in person in June in Brno – both to gather and discuss Packit-related topics and also to be part of DevConf.CZ conference. To not need to dive into everything happening during that time in this text, take a look at <a href=\"https://packit.dev/posts/devconf-2024\" target=\"_blank\" rel=\"noopener noreferrer\">our blog post</a>. We organised a successful workshop in the Red Hat Brno office and took multiple talks, notably a <a href=\"https://www.youtube.com/watch?v=7n8pypmrQh4\" target=\"_blank\" rel=\"noopener noreferrer\">showcase</a> of user success stories presented by our fellow users.</p><p>During summer and again after a couple of years, we had the pleasure to have a student working on a Packit-related task as part of the Google Summer of Code. This time, the functionality was going outside of the Fedora ecosystem, namely to support OBS (the openSUSE build and distribution service). We want to thank <a href=\"https://github.com/rxbryan\" target=\"_blank\" rel=\"noopener noreferrer\">Brian Elle</a> who worked on this, and <a href=\"https://github.com/dcermak\" target=\"_blank\" rel=\"noopener noreferrer\">Dan Čermák</a> who took the lead on this from the openSUSE side and is currently polishing the code so it can be introduced into Packit’s codebase without worrying about maintainability.</p><p>Another regular event during the year is a Fedora yearly conference – <a href=\"https://fedoraproject.org/flock/2024/\" target=\"_blank\" rel=\"noopener noreferrer\">Flock</a>. This time happening in Rochester and thanks to Fedora’s sponsorship, both <a href=\"https://fosstodon.org/@lbarcziova\" target=\"_blank\" rel=\"noopener noreferrer\">Laura</a> and <a href=\"https://mastodonczech.cz/@lachmanfrantisek\" target=\"_blank\" rel=\"noopener noreferrer\">František</a> could take part. Similar to DevConf.CZ we’ve covered all the details in a <a href=\"https://packit.dev/posts/flock_2024_diary\" target=\"_blank\" rel=\"noopener noreferrer\">separate blog post</a>. Just to mention the talks presented, we took <a href=\"https://cfp.fedoraproject.org/flock-2024/talk/HCBLBX/\" target=\"_blank\" rel=\"noopener noreferrer\">one</a> session covering Fedora automation and our journey to it and a <a href=\"https://cfp.fedoraproject.org/flock-2024/talk/SHQHK8/\" target=\"_blank\" rel=\"noopener noreferrer\">second one</a> with <a href=\"https://matrix.to/#/@jhavlin:fedora.im?web-instance%5Belement.io%5D=chat.fedoraproject.org\" target=\"_blank\" rel=\"noopener noreferrer\">Jan Havlín</a> from the Testing Farm to show people various testing use cases and all the news that was delivered on this field.</p><p>The second half of the year was spent finishing all the initiatives we’d worked on for some time. The long-awaited feature was not to require a git upstream for Fedora release automation. This wasn’t so simple because of the old decision to build Packit on the concept of related git repositories – one representing upstream and one downstream. (And maybe one for the source-git, but that’s a <a href=\"https://packit.dev/source-git/status\" target=\"_blank\" rel=\"noopener noreferrer\">story</a> for another time.) Luckily, all the hard work was done and many packages can now use Packit.</p><p>Another feature and another change of Packit’s internal plumbings is the way to <a href=\"https://packit.dev/posts/non-git-upstreams-support\" target=\"_blank\" rel=\"noopener noreferrer\">avoid having divergent branching</a> when releasing to multiple Fedora (or EPEL) branches. Thanks to this, the commits between branches can now be shared and the history can be linear.</p><p>This is still not all. Another huge feature spreading across multiple packages is <a href=\"https://packit.dev/docs/fedora-releases-guide/releasing-multiple-packages\" target=\"_blank\" rel=\"noopener noreferrer\">the support for side-tags</a>. It’s a vast improvement and enabler for various package groups that need to control many packages together. And it’s finally there!</p><p>And this is still not all for this year. We love collaborating on features and one such collaboration was/is with <a href=\"https://fosstodon.org/@siteshwar\" target=\"_blank\" rel=\"noopener noreferrer\">Siteshwar Vashisht</a> on integrating Packit with <a href=\"https://openscanhub.dev/\" target=\"_blank\" rel=\"noopener noreferrer\">OpenScanHub</a> so Packit users can run static analysis without much effort. Later during the year, we managed to properly report differential scans (so you can check only new findings.) If you are interested in this (or would like to know why one needs to care), look at Situ’s presentation on <a href=\"https://www.youtube.com/watch?v=rcuIvAttWgY&amp;pp=ygUdZGV2Y29uZiBzaXRlc2h3YXIgb3BlbnNjYW5odWI%3D\" target=\"_blank\" rel=\"noopener noreferrer\">DevConf.CZ</a> or <a href=\"https://www.youtube.com/watch?v=lp7UECNg7qY\" target=\"_blank\" rel=\"noopener noreferrer\">Cauldron</a> conference. You can also visit Brussels next year and <a href=\"https://mastodonczech.cz/@lachmanfrantisek\" target=\"_blank\" rel=\"noopener noreferrer\">František</a> and <a href=\"https://fosstodon.org/@siteshwar\" target=\"_blank\" rel=\"noopener noreferrer\">Siteshwar Vashisht</a> <a href=\"https://cfp.fedoraproject.org/centos-connect-2025/talk/review/EW7PWKP8E3FJPVYHUTARFZRNURYZBTDA\" target=\"_blank\" rel=\"noopener noreferrer\">should present</a> the integration on the <a href=\"https://connect.centos.org/\" target=\"_blank\" rel=\"noopener noreferrer\">CentOS Connect</a>. Feedback for this functionality is welcome <a href=\"https://github.com/packit/packit/discussions/2371\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>.</p><p>After all these big achievements and many small and big improvements, the <a href=\"https://packit.dev/posts/packit_1_0_0_action_required\" target=\"_blank\" rel=\"noopener noreferrer\">time has come to release Packit v1.0.0</a>. Everything is now prepared, and we are giving people time to update their configuration files. (Since we love automation and pull request-based workflows, the affected users should have received a pull request with the changes required.)</p><p>So, quite a strong year, wasn’t it?</p><p>If you rather want to check some hard data, let’s look at the usage trend charts from last year. We’ve managed to double the number of projects! As you can see, there is a strong trend in the Fedora automation space overnumbering the projects with upstream Copr builds and/or tests.</p><p><img loading=\"lazy\" alt=\"Trend chart of onboarded project in year 2024\" src=\"/assets/images/2024-onboarding-chart-79dab44b5c3b112d3d062fb63872ed43.png\" width=\"1412\" height=\"433\" class=\"img_ev3q\"></p><p>And now, we are slowly moving towards the next year. So, what you can expect from us?</p><p>We have two ideas on how to have a bigger impact (a positive one, we truly believe) in Fedora. Since we believe Fedora is about community, we have prepared two Fedora Change Proposals so everyone can provide feedback on what we would like to introduce.</p><ul><li><a href=\"https://discussion.fedoraproject.org/t/f42-change-proposal-automated-onboarding-to-packit-release-automation-for-new-packages-system-wide/139530\" target=\"_blank\" rel=\"noopener noreferrer\">F42 Change Proposal: Automated onboarding to Packit release automation for new packages (system-wide)</a> (Yes, we would like to bring Packit to new packages and ideally to people who might not be aware of Packit.)</li><li><a href=\"https://fedoraproject.org/wiki/Changes/PackitDistgitCI\" target=\"_blank\" rel=\"noopener noreferrer\">Packit as a dist-git CI</a> (We believe we can build on our successful collaboration with Testing Farm and provide a better dist-git CI for Fedora.)</li></ul><p>We would also like to give our dashboard more love. We used to prioritise other features, but we can’t postpone it forever. With the help of <a href=\"https://snug.moe/@Venefilyn\" target=\"_blank\" rel=\"noopener noreferrer\">Freya</a>, we plan to start with user research and try to make the dashboard more user-friendly as part of <a href=\"https://packit.dev/posts/project-mycorrhiza\" target=\"_blank\" rel=\"noopener noreferrer\">Project Mycorrhiza</a>.</p><p>To be closer to Fedora, we would also like to move our deployments to the Fedora OpenShift Cluster. The discussions are ongoing, and luckily, we might be able to do this soon.</p><p>And if you want to meet us in person, a good chance is <a href=\"https://connect.centos.org/\" target=\"_blank\" rel=\"noopener noreferrer\">CentOS Connect</a>, <a href=\"http://DevConf.CZ\" target=\"_blank\" rel=\"noopener noreferrer\">DevConf.CZ</a> or <a href=\"https://fedoraproject.org/flock/\" target=\"_blank\" rel=\"noopener noreferrer\">Flock</a>.</p><p>Hopefully, the following year will be at least as successful as the previous one. Thanks everyone for your support. We have the pleasure to have a friendly and grateful userbase that is a pleasure to work with and for. All the best for the new year!</p>",
            "url": "https://packit.dev/posts/packit-in-2024",
            "title": "Packit in 2024",
            "summary": "We are reaching the end of the year and it’s a good time to look back at the Packit highlights of this year. And it was a year!",
            "date_modified": "2024-12-23T00:00:00.000Z",
            "author": {
                "name": "František Lachman",
                "url": "https://github.com/lachmanfrantisek"
            },
            "tags": [
                "2024",
                "yearly-features",
                "summary"
            ]
        },
        {
            "id": "https://packit.dev/posts/packit_1_0_0_action_required",
            "content_html": "<p>After 105 minor releases we are almost ready to announce our first major release, Packit 1.0.0!</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"whats-new\">What's New<a href=\"#whats-new\" class=\"hash-link\" aria-label=\"Direct link to What's New\" title=\"Direct link to What's New\">​</a></h2><p>We will <strong>remove all long-deprecated keys from the configuration file</strong>.</p><p><code>packit-service</code> jobs are tied with <code>packit CLI</code>. The <em>packit configuration code</em> is defined in the <code>packit</code> package and used by the <code>packit-service</code>.\nSo be aware that for those projects still using the deprecated keys in their <code>packit.yaml</code> configuration file we have created a migration pull request.</p><p>Please, <strong>check if you have any new PR for your project created by the packit-service bot account, review and merge it</strong>. Otherwise, you might experience issues with the <code>packit-service</code> jobs once the new packit version is released.</p><p>We plan to release Packit 1.0.0 in <strong>January 2025</strong>.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"list-of-removed-keys\">List of removed keys<a href=\"#list-of-removed-keys\" class=\"hash-link\" aria-label=\"Direct link to List of removed keys\" title=\"Direct link to List of removed keys\">​</a></h3><ul><li>Job type <code>build</code> has been changed to <a href=\"https://packit.dev/docs/configuration/upstream/copr_build\" target=\"_blank\" rel=\"noopener noreferrer\"><code>copr_build</code></a>.</li><li>Job type <code>production_build</code> has been changed to <a href=\"https://packit.dev/docs/configuration/upstream/upstream_koji_build\" target=\"_blank\" rel=\"noopener noreferrer\"><code>upstream_koji_build</code></a>.</li><li>Key <code>upstream_project_name</code> has been changed to <a href=\"https://packit.dev/docs/configuration#upstream_package_name\" target=\"_blank\" rel=\"noopener noreferrer\"><code>upstream_package_name</code></a>.</li><li>Key <code>synced_files</code> has been changed to <a href=\"https://packit.dev/docs/configuration#files_to_sync\" target=\"_blank\" rel=\"noopener noreferrer\"><code>files_to_sync</code></a>.</li></ul><p>The job types were renamed for clarity when we introduced more job types.\nThe <code>upstream_project_name</code> was renamed to <code>upstream_package_name</code> to be more specific.\nThe <code>files_to_sync</code> key has a more explicit behavior than the old <code>synced_files</code> key.</p>",
            "url": "https://packit.dev/posts/packit_1_0_0_action_required",
            "title": "Packit 1.0.0 countdown - action may be required",
            "summary": "After 105 minor releases we are almost ready to announce our first major release, Packit 1.0.0!",
            "date_modified": "2024-12-09T12:00:00.000Z",
            "author": {
                "name": "Maja Massarini",
                "url": "https://github.com/majamassarini"
            },
            "tags": [
                "configuration"
            ]
        },
        {
            "id": "https://packit.dev/posts/project-mycorrhiza",
            "content_html": "<p>This term has been thrown around a bit in issues here and there relating to the dashboard and\npeople usually get confused, and rightfully so! Lets dive in and see what Project Mycorrhiza\nis and why we chose this name.</p><p><img loading=\"lazy\" alt=\"Photo of beech trees in a forest\" src=\"/assets/images/forest-313f56ef49c00c34156b3a8adb1dead8.jpg\" title=\"New beech leaves, Gribskov Forest in the northern part of Sealand, Denmark.\" width=\"1150\" height=\"1080\" class=\"img_ev3q\">\nPhoto by <a href=\"https://commons.wikimedia.org/wiki/User:Malene\" target=\"_blank\" rel=\"noopener noreferrer\">Malene Thyssen</a> - Own work, <a href=\"http://creativecommons.org/licenses/by-sa/3.0/\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"Creative Commons Attribution-Share Alike 3.0\">CC BY-SA 3.0</a>, <a href=\"https://commons.wikimedia.org/w/index.php?curid=752225\" target=\"_blank\" rel=\"noopener noreferrer\">Link</a></p><hr><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"tldr\">TL;DR<a href=\"#tldr\" class=\"hash-link\" aria-label=\"Direct link to TL;DR\" title=\"Direct link to TL;DR\">​</a></h2><p>Project Mycorrhiza is a temporary name to encompass the work relating to what the next generation\nPackit dashboard could look like by seeing how developer time can be saved, minimizing\ncomplexity, reducing context switching, and providing results faster. Research going into this\nwill likely improve Packit overall and even be useful for other related teams. 'Mycorrhiza' means\na symbiotic network between plants and fungi to share nutrients, fats, and sugars between each other to grow.</p><p>We will consolidate existing research and begin to interview more teams on what developers are\nmissing the most. Our plan is for this to be done before 2024, likely by December.</p><hr><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"abstract\">Abstract<a href=\"#abstract\" class=\"hash-link\" aria-label=\"Direct link to Abstract\" title=\"Direct link to Abstract\">​</a></h2><p>Before I explain what Project Mycorrhiza is and what it's about, lets talk about\nthe Packit dashboard and why it's been getting so much love from me the past year.</p><p>It's no surprise that Packit is used within a lot of different projects around\nFedora, which includes <a href=\"https://github.com/oamg/convert2rhel\" target=\"_blank\" rel=\"noopener noreferrer\">Convert2RHEL</a> that I'm\na developer of. But I've always felt like Packit's dashboard has missed the mark on\nbeing the go-to for getting an overview for the pipeline, results, or even the\nproject itself.</p><p>Since I like making websites better for my own benefit, I've been spending a huge amount of my own\ntime the past year to gradually improve the Packit dashboard to prepare it for something\nbigger. Which is where Project Mycorrhiza comes in.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"whats-mycorrhiza-and-mycorrhizal-network\">What's mycorrhiza and mycorrhizal network?<a href=\"#whats-mycorrhiza-and-mycorrhizal-network\" class=\"hash-link\" aria-label=\"Direct link to What's mycorrhiza and mycorrhizal network?\" title=\"Direct link to What's mycorrhiza and mycorrhizal network?\">​</a></h2><div class=\"theme-admonition theme-admonition-note alert alert--secondary admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z\"></path></svg></span>note</div><div class=\"admonitionContent_S0QG\"><p>This is heavily simplified for the purpose of getting a quick overview. I encourage you\nto read more about <a href=\"https://en.wikipedia.org/wiki/Mycorrhiza\" target=\"_blank\" rel=\"noopener noreferrer\">mycorrhiza on the Wikipedia article about it</a>\nand any related articles!</p></div></div><p>You might be familiar with something called mycelium, the network of root-like structures that\nfungi form. I'm assuming most of you have seen this form on food before, such as bread\nthat grew mold.</p><p>The mycelia helps fungi get nutrients and get enough food to grow mushrooms!\nSome are just terrible to be around, some are interesting to look at but relatively toxic, and\nsome are even edible. Those same labels I applied to the mushrooms are something plants and trees\nsort of do as well!</p><p>A mycorrhizal network is a symbiosis between fungi and flowers and trees.\nYou have already seen one too as the photo above is a bunch of Beech trees that\nare \"<a href=\"https://en.wikipedia.org/wiki/Ectomycorrhiza\" target=\"_blank\" rel=\"noopener noreferrer\">ectomyccorhizal</a>\"!\nWhat it means is that nutrients are shared between the two, the fungi spreads out mycelia in the soil\nand transfers nutrients to the tree, and the tree provides sugar and fat back to the fungi.</p><p>Since my project relates to integrating more services and getting a better\npackaging ecosystem, I chose the name Project Mycorrhiza to put emphasis on the symbiosis between\nthe different tools.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"project-mycorrhiza\">Project Mycorrhiza<a href=\"#project-mycorrhiza\" class=\"hash-link\" aria-label=\"Direct link to Project Mycorrhiza\" title=\"Direct link to Project Mycorrhiza\">​</a></h2><p>Now with the name explanation out of the way. First and foremost, this should be seen as a kind\nof idea or kind of a temporary working group to see about the future goals of Packit and\nhow the Packit dashboard fits into the Fedora service ecosystem. The Mycorrhiza name itself\nwill only stick around for the duration of this investigation and alignment. Once it is done\nwe will likely drop or change it. 2. Kicks off integration tests through <a href=\"https://testing-farm.io/\" target=\"_blank\" rel=\"noopener noreferrer\">Testing Farm</a>.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"fedora-packaging-ecosystem\">Fedora packaging ecosystem<a href=\"#fedora-packaging-ecosystem\" class=\"hash-link\" aria-label=\"Direct link to Fedora packaging ecosystem\" title=\"Direct link to Fedora packaging ecosystem\">​</a></h3><p>There is a lot of packages out there that ships in Fedora, be it through <a href=\"https://copr.fedorainfracloud.org/\" target=\"_blank\" rel=\"noopener noreferrer\">Copr</a> repositories or\nofficial Fedora repositories. For products that ship downstream there is also a downstream\nrelease automation! But what they most have in common is a continuous integration\nworkflow to ensure that they can release whenever they want. Although Packit helps with this\ntremendously, it's only an orchestrator to make the process easier and more automated.</p><p>For those that already ship to Fedora, you likely use Copr to do either general releases or just\nto do development builds to test on. Packit can ensure that new commits</p><ol><li>Start a Copr build for the commit with a good name.</li><li>Kicks off integration tests through <a href=\"https://testing-farm.io/\" target=\"_blank\" rel=\"noopener noreferrer\">Testing Farm</a>.</li><li>Show the results in GitHub or GitLab workflows.</li></ol><p>Packit can do a whole bunch more than just this and even go into finer granularity, making it\na very powerful service to use when it comes to packaging. However, when it comes to\ndebugging or seeing results of tests. Packit in the current state rarely does anything more than\nproviding links to the results in Copr, <a href=\"https://koji.fedoraproject.org/koji/\" target=\"_blank\" rel=\"noopener noreferrer\">Koji</a>, Testing Farm, and so on.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"next-generation-dashboard\">Next-generation dashboard<a href=\"#next-generation-dashboard\" class=\"hash-link\" aria-label=\"Direct link to Next-generation dashboard\" title=\"Direct link to Next-generation dashboard\">​</a></h3><p>This is where I see the most improvement for consolidating this information. There is so much\nwe could do and I can see so many fun projects given the currently small scope of the Packit\ndashboard. But we need to focus first and foremost on what users want, and although I have\na strong belief I know what would be good, everything mentioned here will need to be followed-up\nwith user interviews and general opinions from users before long-term initiatives will be worked on.</p><p>One of the first thing I noticed when I was onboarded to Packit with Convert2RHEL was the lack of\nproject overview. I wanted to see how builds and tests throughout all PRs were doing on the project\nand ideally getting results without having to leave the page. Instead, I found an undeveloped\nproject page, a pipeline view that showed all pipelines, individual result pages with links\nto build logs and test results.</p><p>That theme grows abundant throughout the dashboard as well and indicates so much room for\nimprovement.</p><h4 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"incorporating-services-into-packit-dashboard\">Incorporating services into Packit dashboard<a href=\"#incorporating-services-into-packit-dashboard\" class=\"hash-link\" aria-label=\"Direct link to Incorporating services into Packit dashboard\" title=\"Direct link to Incorporating services into Packit dashboard\">​</a></h4><p>To reduce the context switching I've experienced throughout it would be great to incorporate\ninformation (and potentially actions) from other services such as Copr and Testing Farm.</p><p>In particular, both Copr and Testing Farm provide logs to how things went. We have the potential\nhere to not only include the logs, but improve the workflow through the use of the existing\nPackit pipeline.</p><p>We could load logs, parse them for relevant information, follow-build logs (this is dependent on\nthird parties mostly), and even see about providing notifications on the go for when the results\nare in.</p><p>Copr has an API that can be utilized for this, and so does Testing Farm, which is how they\nprovide results to their own Testing Farm results page.</p><p>Having all of these logs in one section and in particular a unified style would be super\nbeneficial to avoid having to re-parse things.\n<a href=\"https://log-detective.com\" target=\"_blank\" rel=\"noopener noreferrer\">Log Detective</a>, a project to help parse logs and provide information on why builds failed, can\nLog Detective, a project to help parse logs and provide information on why builds failed, can\nalso be integrated to help their project get more logs to train with (opt-in of course).</p><h4 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"product-overview\">Product overview<a href=\"#product-overview\" class=\"hash-link\" aria-label=\"Direct link to Product overview\" title=\"Direct link to Product overview\">​</a></h4><p>If you manage a product and for instance use Testing Farm you know the pain of waiting for the\nresults to happen. Especially so when you are waiting on test runs within several PRs/MRs.</p><p>Getting a better view for the project view to display all the pipelines for the repository\nwould not only help get a holistic view for how things are going, but allow you to instantly\nsee and even be notified of the results.</p><h4 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"filters-search--sorting\">Filters, search, &amp; sorting<a href=\"#filters-search--sorting\" class=\"hash-link\" aria-label=\"Direct link to Filters, search, &amp; sorting\" title=\"Direct link to Filters, search, &amp; sorting\">​</a></h4><p>In the current Packit dashboard you can even see a what's supposed to be search field that\nallows you to search for the forge (like GitHub), git organizations, and git repositories.\nIf you've tried to use this you've quickly realized this needs an exact name and is more of a\n\"quick-link\" to the respective view than a search.</p><p><img loading=\"lazy\" alt=\"Search-like inputs in the dashboard&amp;#39;s project view\" src=\"/assets/images/project-search-6c5794658dcc41ec2d875ff33b6162a2.png\" width=\"1178\" height=\"295\" class=\"img_ev3q\"></p><p>What is seen in most other tables throughout as well, including the project view, is that we\ndon't have any filters available. The sorting is also done by most recent first, but what if\nyou want to sort by PR for example? That is missing in the current implementation.</p><p>Having a search to get the results quickly would also be good, which would be similar to filter\nbut just a free-form field basically.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"research-and-interviews\">Research and interviews<a href=\"#research-and-interviews\" class=\"hash-link\" aria-label=\"Direct link to Research and interviews\" title=\"Direct link to Research and interviews\">​</a></h2><p>So what's next? There is a lot of great information out there already, such as interviews\nby the <a href=\"https://www.uxd-hub.com/\" target=\"_blank\" rel=\"noopener noreferrer\">Red Hat UXD team</a>. We will be going through\ndata reported for the general lacking features developers want or are frustrated with,\nas well as following-up with Packit users with a more Packit-scoped interview to\nsee how on the goal our research is. Depending on this research, which we hope to be done\nbeginning of 2025 in the worst-case scenario, we will start to plan out the work\nto make the Packit service and Packit dashboard be the best it could be.</p><p>We will of course continue to improve everything until then, Packit dashboard will get gradual\nimprovements throughout the rest of the year and Packit will continue to work on the goals they've\nannounced for the quarter.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"links\">Links<a href=\"#links\" class=\"hash-link\" aria-label=\"Direct link to Links\" title=\"Direct link to Links\">​</a></h2><ul><li><a target=\"_blank\" href=\"/assets/files/Pitch for NextGen Packit Dashboard-1c2c428c6a602381d424f51f74bb2982.pdf\">Pitch for NextGen Packit Dashboard.pdf</a></li></ul>",
            "url": "https://packit.dev/posts/project-mycorrhiza",
            "title": "Packit dashboard and Project Mycorrhiza",
            "summary": "This term has been thrown around a bit in issues here and there relating to the dashboard and",
            "date_modified": "2024-11-01T10:00:00.000Z",
            "author": {
                "name": "Freya Gustavsson",
                "url": "https://github.com/Venefilyn"
            },
            "tags": [
                "Project Mycorrhiza",
                "dashboard",
                "ux",
                "testing-farm",
                "logs",
                "copr"
            ]
        },
        {
            "id": "https://packit.dev/posts/non-divergent-dist-git-branches",
            "content_html": "<p>Were you annoyed by Packit creating divergent branches in your package's dist-git repository? You'll be happy to know that Packit now supports a new <code>dist_git_branches</code> syntax that enables fast-forwarding commits between branches.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"whats-new\">What's New<a href=\"#whats-new\" class=\"hash-link\" aria-label=\"Direct link to What's New\" title=\"Direct link to What's New\">​</a></h2><p>When defining a <code>propose-downstream</code> or <code>pull-from-upstream</code> job, you can use the new <code>dist_git_branches</code> syntax.</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  dist_git_branches:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    rawhide:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      fast_forward_merge_into: [fedora-branched]</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    epel-9: {}</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>In this example, Packit runs the downstream synchronization process for the <code>rawhide</code> and <code>epel-9</code> branches as usual. Additionally, Packit opens a new pull request, reusing the commit from <code>rawhide</code>, for every <code>fedora-branched</code> branch, allowing it to be fast-forwarded when merging.</p><p>Do you want to know more? Look at the <a href=\"/docs/fedora-releases-guide/non-divergent-dist-git-branches\">non-divergent dist-git branches guide</a></p>",
            "url": "https://packit.dev/posts/non-divergent-dist-git-branches",
            "title": "No more divergent dist-git branches with Packit!",
            "summary": "Were you annoyed by Packit creating divergent branches in your package's dist-git repository? You'll be happy to know that Packit now supports a new distgitbranches syntax that enables fast-forwarding commits between branches.",
            "date_modified": "2024-10-28T10:46:18.000Z",
            "author": {
                "name": "Maja Massarini",
                "url": "https://github.com/majamassarini"
            },
            "tags": [
                "propose-downstream",
                "pull-from-upstream",
                "downstream",
                "configuration"
            ]
        },
        {
            "id": "https://packit.dev/posts/non-git-upstreams-support",
            "content_html": "<p>We are happy to announce that support for non-git upstreams in the <a href=\"/docs/configuration/downstream/pull_from_upstream\"><code>pull_from_upstream</code> job</a> is here!\nThis enhancement simplifies configuration by removing the need to define <a href=\"/docs/configuration#upstream_project_url\"><code>upstream_project_url</code></a>,\nopening the door for more use cases, while also simplifying the onboarding in general.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"what-changed\">What changed<a href=\"#what-changed\" class=\"hash-link\" aria-label=\"Direct link to What changed\" title=\"Direct link to What changed\">​</a></h2><p>Previously, the <code>upstream_project_url</code> configuration option was required to point to a git repository for the <code>pull_from_upstream</code> job to work.\nNow, with this update, it’s no longer necessary, allowing the job to sync the releases also for packages with non-git upstreams.\nEven for packages having git-based upstreams, this change allows to skip configuration of this option\nwhen the repository interaction is unnecessary.</p><p>Without <code>upstream_project_url</code> configured, no repository will be cloned, and no git interaction will occur.\nThe configured <a href=\"/docs/configuration/actions\">actions</a> will be executed in an arbitrary directory.\nAdditionally, related configuration options such as <a href=\"/docs/configuration#upstream_tag_template\"><code>upstream_tag_template</code></a>, <a href=\"/docs/configuration#upstream_tag_include\"><code>upstream_tag_include</code></a>, and <a href=\"/docs/configuration#upstream_tag_exclude\"><code>upstream_tag_exclude</code></a> will be ignored.\nIf you need to filter releases, this can still be done on the <a href=\"https://release-monitoring.org/\" target=\"_blank\" rel=\"noopener noreferrer\"><code>release-monitoring</code></a> project settings side.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"configuration-generation-automation\">Configuration generation automation<a href=\"#configuration-generation-automation\" class=\"hash-link\" aria-label=\"Direct link to Configuration generation automation\" title=\"Direct link to Configuration generation automation\">​</a></h2><p>This update also makes automation easier. You can use the <a href=\"/docs/cli/dist-git/init\"><code>packit dist-git init</code> command</a> to generate your configuration\nfile without specifying <code>--upstream-git-url</code>, enabling easier scripting for mass onboarding of your packages.\nFor more advanced use cases, additional arguments can still be added to adjust the configuration as needed.</p>",
            "url": "https://packit.dev/posts/non-git-upstreams-support",
            "title": "Non-git upstreams support and simplified configuration for easier onboarding!",
            "summary": "We are happy to announce that support for non-git upstreams in the pullfromupstream job is here!",
            "date_modified": "2024-09-18T08:46:18.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "pull-from-upstream",
                "downstream",
                "configuration"
            ]
        },
        {
            "id": "https://packit.dev/posts/flock_2024_diary",
            "content_html": "<p>It’s been a month since two Packit members (<a href=\"https://fosstodon.org/@lbarcziova\" target=\"_blank\" rel=\"noopener noreferrer\">Laura</a> and <a href=\"https://mastodonczech.cz/@lachmanfrantisek\" target=\"_blank\" rel=\"noopener noreferrer\">František</a>) attended Flock, the annual Fedora conference, in Rochester. Let’s see some highlights from our journey There and Back Again. Sadly the travel there wasn’t as expected at all, but luckily the tornadoes did not stop us and we both made it to Rochester.</p><h1>Packit contributions</h1><p>We prepared two talks for the Flock attendees. If you missed it, the recordings are available. But here’s what we presented:</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"packit-release-automation-journey-recording\">Packit release automation journey (<a href=\"https://www.youtube.com/watch?v=x-o91dkv1Cg\" target=\"_blank\" rel=\"noopener noreferrer\">recording</a>)<a href=\"#packit-release-automation-journey-recording\" class=\"hash-link\" aria-label=\"Direct link to packit-release-automation-journey-recording\" title=\"Direct link to packit-release-automation-journey-recording\">​</a></h2><p>This one mainly targeted the Fedora maintainers and described how you can use Packit for your packages. The basic workflow has been here for some time but we’ve presented a couple of interesting news about what we are currently working on:</p><p>The requirement to have a git repository representing is now gone. By NOT specifying the <code>upstream_project_url</code> config option, Packit will not try to clone or interact with the upstream via git. This is especially useful if the upstream project does not use git, or you just don’t need it (e.g. packages using language-specific repositories like PyPI).</p><p>If you are interested in having a nice git tree, you’ll welcome that the Packit team is currently working on making it possible t<a href=\"https://github.com/packit/packit-service/pull/2478\" target=\"_blank\" rel=\"noopener noreferrer\">o avoid diverging branches when doing release syncing</a>.</p><p>Another long-time-awaited feature is support for releasing package groups using side-tags. Since Flock, Nikola from the Packit team polished the functionality and even created a <a href=\"https://packit.dev/docs/fedora-releases-guide/releasing-multiple-packages\" target=\"_blank\" rel=\"noopener noreferrer\">dedicated documentation page</a>e describing how to use it.</p><p>And that’s not all, there are also two related efforts we are in the early phases. One is about using Packit to run reverse-dependency checks/builds. The update is that Mikolaj Izdebski (thanks a lot<!-- -->!<!-- -->) re-enabled a Copr plugin in Koschei so it should now be possible to run the checks independently to Koji which is better for ad-hock CI checks but also to not produce extra load on Koji itself. Ideally, this would be available for both upstream and dist-git pull requests. And speaking of the dist-git pull requests, there is a discussion about <a href=\"https://pagure.io/fedora-ci/general/issue/476\" target=\"_blank\" rel=\"noopener noreferrer\">the future of Fedora CI</a> and Zuul, we agreed within a team to take a look and see if we can’t help with that. The reasons and questions to answer are covered in the talk.</p><p>And that’s still not all. There is also a Google Summer of Code project by Bryan Elee as part of which an integration for OpenBuildService is being implemented. Stay tuned. The CLI support is nearly there.</p><p>And lastly, project Myccorhisa. Our effort to create a unified dashboard for various Fedora-related services. Want to help us better understand the needs? Please, describe your usual workflow in <a href=\"https://packit.limesurvey.net/project-mycorrhiza\" target=\"_blank\" rel=\"noopener noreferrer\">this form</a>.</p><p>But we were not speaking just about the features but also how we work and how we help people to get on board.</p><p>After the talk, there was an interesting discussion. One of the suggestions was to onboard new packages to Packit automatically – we thought about it within a team and <a href=\"https://github.com/packit/packit-service/issues/2506\" target=\"_blank\" rel=\"noopener noreferrer\">will work</a> on opening a pull request with the configuration and most importantly, a description of Packit.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"packit--testing-farm-and-fedora-still-happily-testing-upstream-projects-recording\">Packit <!-- -->+<!-- --> Testing Farm and Fedora: still happily testing upstream projects (<a href=\"https://www.youtube.com/watch?v=F7C82Fwdvis\" target=\"_blank\" rel=\"noopener noreferrer\">recording</a>)<a href=\"#packit--testing-farm-and-fedora-still-happily-testing-upstream-projects-recording\" class=\"hash-link\" aria-label=\"Direct link to packit--testing-farm-and-fedora-still-happily-testing-upstream-projects-recording\" title=\"Direct link to packit--testing-farm-and-fedora-still-happily-testing-upstream-projects-recording\">​</a></h2><p>For the second talk, we were joined by <a href=\"https://matrix.to/#/@jhavlin:fedora.im?web-instance%5Belement.io%5D=chat.fedoraproject.org\" target=\"_blank\" rel=\"noopener noreferrer\">Jan Havlín</a> from the Testing Farm team and the main aim of the talk was to show various new and old ways how to use Packit for your project. Rather than showing documentation, we presented the features on real projects and how they configure this so you can easily do the same. You might have seen this style of presentation from us, but don’t be fooled just by the structure, there were a couple of new features presented as well.</p><p>One big achievement is a collaboration with <a href=\"https://twitter.com/SiteshwarV\" target=\"_blank\" rel=\"noopener noreferrer\">Siteshwar Vashisht</a> on integrating OpenScanHub to run static analysis for your projects. The setup is very simple, just set up Packit to run builds both for the pull requests and your <code>main</code> branch and Packit will trigger a differential scan on pull requests for you. We have a <a href=\"/posts/openscanhub-prototype\">separate blog post</a> about this. There is also <a href=\"https://situ.im/posts/openscanhub-fedora-and-packit\" target=\"_blank\" rel=\"noopener noreferrer\">one</a> written by Situ.</p><p>Also, Jan showed how you can newly generate your own Testing Farm tokens using your Fedora account – but when using Packit, this is not needed and Packit will take care of this for you. But maybe you want to use this to play with the Testing Farm environment locally – you can newly reserve a machine thanks to this token.</p><h1>Other talks and activities</h1><p>During the Flock, we’ve quite intensively discussed the possibility of running Packit in Fedora infrastructure. Why? Currently, Packit is run on a RedHat-hosted OpenShift instance, but Packit’s main target is Fedora and we don’t communicate (and also don’t want to) with Red Hat internal services. Also, to show clearly the users that Packit is part of Fedora. On this topic, there was a <a href=\"https://cfp.fedoraproject.org/flock-2024/talk/VL7D3H/\" target=\"_blank\" rel=\"noopener noreferrer\">talk</a> held by David Kirwan about Communishift which is here for users to deploy their projects on Fedora-hosted OpenShift. We can use it, but we discussed with CPE team, that OpenShift managed by CPE team and used for other Fedora infrastructure systems might be a better fit. <a href=\"https://fosstodon.org/@m4tt_314\" target=\"_blank\" rel=\"noopener noreferrer\">Matej Focko</a> from our team collected our requirements and we were asked to communicate this publicly via <a href=\"https://discussion.fedoraproject.org/\" target=\"_blank\" rel=\"noopener noreferrer\">https://discussion.fedoraproject.org</a>.</p><p>A lot of interest was caught by the talk about Fedora dist-git forge replacement. <a href=\"https://matrix.to/#/@humaton:fedora.im?web-instance%5Belement.io%5D=chat.fedoraproject.org\" target=\"_blank\" rel=\"noopener noreferrer\">Tomáš Hrčka</a> quite nicely covered the current state that his team was asked to do the technical research but did not make any decision. Packit has even been included in their research which we are thankful for. Currently, we have two candidates – <a href=\"https://forgejo.org/\" target=\"_blank\" rel=\"noopener noreferrer\">Forgejo</a> and GitLab. Both have been deployed for testing purposes and can be accessed via Fedora staging accounts. So far, the Forgejo seems like a better choice both because of extensibility and ease of deployment/maintenance but nothing has been decided yet. There are two Packit-related topics – if Forgejo is picked, we need to implement its support in ogr, our library for git-forge communication, but hopefully, this would be the only place for change, let’s see…;) Another interesting thing is that there is an idea to provide dist-git functionality not directly on the git-forge, but as a separate dashboard/page and this might be worth collaborating as part of the project Myccorhisa.</p><p>If you are interested in testing in Fedora, you must watch <a href=\"https://cfp.fedoraproject.org/flock-2024/talk/8U9GKX/\" target=\"_blank\" rel=\"noopener noreferrer\">the talk</a> by <a href=\"https://fosstodon.org/@adamw\" target=\"_blank\" rel=\"noopener noreferrer\">Adam Williamson</a> with a long title <em>The hard problems: towards stronger checks on dependencies and compose inputs in Fedora.</em> Hopefully, Packit be a part of the solution covered during the talk.</p><p>Thanks to the community aspect of the conference, it was really easy to sit down with anyone and help them with the Packit setup and we’ve managed to onboard a couple of new projects for <a href=\"https://packit.dev/docs/fedora-releases-guide/dist-git-onboarding\" target=\"_blank\" rel=\"noopener noreferrer\">Fedora automation</a>. Usually, people want to do the onboarding at home, alone (which they hardly do) at first, but they are happy to leave with a working setup after a bit of convincing. We can unblock them more easily, and describe anything needed and they are usually surprised at how simple it is..;)</p><p>If you are interested in a talk that was really engaging, take a look at <em>CentOS Stream <!-- -->-<!-- --> a preview of RHEL, a solid base for CentOS SIGs</em> by <a href=\"https://matrix.to/#/@asamalik:fedora.im?web-instance%5Belement.io%5D=chat.fedoraproject.org\" target=\"_blank\" rel=\"noopener noreferrer\">Adam Šamalík</a>. It was a nice walkthrough covering CentOS Stream and its design and processes. Also, a couple of interesting questions followed.</p><p>We also attended the Fedora Infrastructure Hackfest. There were a lot of topics covered, but two had a relation to Packit:</p><ul><li>There is a plan to unify the building of containers across CPE and we’ve suggested to include more teams like Packit since this is not a unique problem. A group of interested people will collaborate on the documentation and tooling.</li><li>There are a lot of packages owned by the <code>infra-sig</code> and it’s hard to maintain them all. A cleanup is needed (e.g. pass the packages to other relevant parties). For the basic packages, we proposed help with Packit onboarding.</li></ul><p>There were many more discussions and talks worth mentioning. Feel free to check the <a href=\"https://cfp.fedoraproject.org/flock-2024/schedule/\" target=\"_blank\" rel=\"noopener noreferrer\">schedule</a> with links to YouTube videos from the recording.</p><h1>Will we meet next year?</h1><p>Could not make it in person this year? Let’s hope we’ll meet next year. Maybe somewhere in Europe this time. Want to influence the future Flock? There is still a day to fill out the <a href=\"https://fedoraproject.limequery.com/flock-2024\" target=\"_blank\" rel=\"noopener noreferrer\">Flock Survey</a>.</p>",
            "url": "https://packit.dev/posts/flock_2024_diary",
            "title": "Packit Flock 2024 Diary",
            "summary": "It’s been a month since two Packit members (Laura and František) attended Flock, the annual Fedora conference, in Rochester. Let’s see some highlights from our journey There and Back Again. Sadly the travel there wasn’t as expected at all, but luckily the tornadoes did not stop us and we both made it to Rochester.",
            "date_modified": "2024-09-05T13:16:18.000Z",
            "author": {
                "name": "František Lachman",
                "url": "https://github.com/lachmanfrantisek"
            },
            "tags": [
                "fedora",
                "flock",
                "conference",
                "2024"
            ]
        },
        {
            "id": "https://packit.dev/posts/openscanhub-prototype",
            "content_html": "<p>We are excited to announce a new experimental feature in our service: the integration of Static\nApplication Security Testing (SAST) using <a href=\"https://openscanhub.fedoraproject.org/\" target=\"_blank\" rel=\"noopener noreferrer\">OpenScanHub</a>.</p><p>OpenScanHub is a service that runs various static analyzers on RPM packages - by default <code>Cppcheck</code>,\n<code>ShellCheck</code> and the static analyzers embedded in <code>GCC</code>.</p><p>Let's have a look at the details of the prototype!</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"why\">Why<a href=\"#why\" class=\"hash-link\" aria-label=\"Direct link to Why\" title=\"Direct link to Why\">​</a></h2><p>This initiative contributes to the <em>shift left</em> effort, aiming to detect and address security\nvulnerabilities earlier in the development process, thus enhancing overall software quality\nand security. By implementing this scanning functionality for <code>fedora-rawhide</code>, the current\ndevelopment version of Fedora, we aim to catch security issues at the earliest possible stage.\nThis is also important as Fedora serves as an upstream platform for downstream distributions\nlike RHEL, ensuring that any vulnerabilities are addressed before they propagate to these other systems.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"functionality\">Functionality<a href=\"#functionality\" class=\"hash-link\" aria-label=\"Direct link to Functionality\" title=\"Direct link to Functionality\">​</a></h2><p>The functionality is designed to automatically\nscan for vulnerabilities and issues in code submitted through pull requests.\nIt is controlled using the configuration option\n<a href=\"/docs/configuration#osh_diff_scan_after_copr_build\"><code>osh_diff_scan_after_copr_build</code></a>,\nwhich is currently set to <code>true</code> by default.\nHowever, even with this option enabled, the differential scanning feature in OpenScanHub\nwill only run for users who have also configured Copr builds with the <code>trigger: commit</code>\nsetting and have matching target branches in their pull request and job configurations.\nThis setup is crucial as it allows Packit to access the base build necessary for differential\nscanning, leading to more precise detection of issues introduced by the pull request.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"setup\">Setup<a href=\"#setup\" class=\"hash-link\" aria-label=\"Direct link to Setup\" title=\"Direct link to Setup\">​</a></h2><p>To utilise this feature, you must ensure that Copr builds for commits are configured,\nalong with Copr builds for pull requests, both set to run for <code>fedora-rawhide-x86_64</code>.\nIf you haven't enabled Copr builds for commits yet, you can add the following job\nconfiguration to the <code>jobs</code> section in your Packit configuration:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> commit</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">branch</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> main</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">targets</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">rawhide</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">preserve_project</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>This configuration assumes that you merge your pull requests into the <code>main</code> branch\nand ensures preserving the Copr project (as opposed to creating a temporary one,\nsee more details <a href=\"https://packit.dev/docs/configuration/upstream/copr_build#optional-parameters\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>).\nYou can also build in your custom Copr project (more details\n<a href=\"https://packit.dev/docs/configuration/upstream/copr_build#using-a-custom-copr-project\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>).</p><p>Here is an example of a scan showing some new findings:</p><p><img loading=\"lazy\" alt=\"Example findings\" src=\"/assets/images/openscanhub-findings-f2924a122fc19a512ff6f652bf318ec5.png\" width=\"1051\" height=\"438\" class=\"img_ev3q\"></p><div class=\"theme-admonition theme-admonition-tip alert alert--success admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_S0QG\"><p>Besides this newly introduced integration with Packit Service, you can also submit scans locally using Packit CLI,\nsee more details in <a href=\"/docs/cli/scan-in-osh\">docs</a>.</p></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"conclusion\">Conclusion<a href=\"#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\">​</a></h2><p>As this is an initial prototype, the configuration and functionality may evolve based on user feedback\n(e.g. reporting the actual results of a scan).\nWe invite you to try out this feature and <a href=\"https://github.com/packit/packit/discussions/2371\" target=\"_blank\" rel=\"noopener noreferrer\">share your thoughts</a> with us\n(e.g. if you would benefit from other <code>osh-cli</code> options to be included).\nFor more information on setting up this feature, see the <a href=\"#setup\">info above</a>.</p><div class=\"theme-admonition theme-admonition-tip alert alert--success admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_S0QG\"><p>A small update. Default configurations for the static analyzers like <code>cppcheck</code> can now be tweaked through <a href=\"/docs/cli/scan-in-osh\"><code>--csmock-args</code> CLI option</a> or <a href=\"/docs/configuration#csmock_args\">a <code>csmock_args</code> option</a> in the Packit's config file. For instance, you can specify arguments like <code>--cppcheck-add-flag=--enable=style</code> to check styling issues as seen in <a href=\"https://openscanhub.fedoraproject.org/task/10066/\" target=\"_blank\" rel=\"noopener noreferrer\">this example run</a> triggered from <a href=\"https://github.com/avahi/avahi/pull/641\" target=\"_blank\" rel=\"noopener noreferrer\">this</a> testing pull-request on Avahi.</p></div></div>",
            "url": "https://packit.dev/posts/openscanhub-prototype",
            "title": "SAST using OpenScanHub is here!",
            "summary": "We are excited to announce a new experimental feature in our service: the integration of Static",
            "date_modified": "2024-08-05T06:46:18.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "copr",
                "srpm",
                "sast",
                "openscanhub",
                "shift left"
            ]
        },
        {
            "id": "https://packit.dev/posts/changelogs",
            "content_html": "<p>Last month, we had the pleasure of engaging with a dynamic audience during our interactive talk on changelogs at the <a href=\"https://www.devconf.info/cz/\" target=\"_blank\" rel=\"noopener noreferrer\">DevConf</a> in Brno, Czech Republic. In case you missed it, you can watch the recording <a href=\"https://youtu.be/TSifrKWNQT0?si=kRlu7PcQZwSwpy0R\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>. Throughout the session, we explored various aspects of changelog usage, including their content, format, and the potential for automation. By asking a series of questions to the attendees, we gathered insights and opinions that highlighted both common practices and divergent viewpoints within the community. In this follow-up article, we aim to summarise the key findings from our discussion, analyse the trends and preferences that emerged, and offer our reflections on the role of changelogs in software development.</p><p><img loading=\"lazy\" alt=\"foto from the conference 1\" src=\"/assets/images/devconf_changelogs1-eff1b9245492904ddb031a20f181f890.jpg\" width=\"1625\" height=\"1083\" class=\"img_ev3q\"></p><p><img loading=\"lazy\" alt=\"foto from the conference 2\" src=\"/assets/images/devconf_changelogs2-7aedea2abc34a2ce6316feb21a428277.jpg\" width=\"1625\" height=\"1083\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"content\">Content<a href=\"#content\" class=\"hash-link\" aria-label=\"Direct link to Content\" title=\"Direct link to Content\">​</a></h2><p>One of the first questions we posed to our audience during the talk was, <em>\"What do you, as a user, like to see in changelogs?\"</em> The most popular elements that the audience showed to like to see in changelogs were <em>breaking changes</em> and <em>new features</em>. Interest in breaking changes indicates that users prioritise being informed about changes that might disrupt their current setup or workflow. As for the features, this shows a strong interest in understanding the latest enhancements and functionalities added to the software. Users appreciate knowing what new capabilities they can leverage. On a similar note, the information about deprecated functionality is also highly valuable for the audience. This can help users plan migrations and avoid using obsolete features. The audience also expressed a clear desire to understand the purpose and context of a new release. Responses such as <em>\"why\"</em>, <em>\"purpose\"</em>, <em>\"reasons\"</em>, <em>\"relations\"</em>, and <em>\"changes motivation\"</em> highlight this need. Understanding the rationale behind changes helps users comprehend the development trajectory and decision-making process. Another interesting response was the desire to know <em>\"am I affected\"</em>, indicating that users primarily care about whether they need to take action or can safely ignore the update. There was also a response <em>\"not a copy of commit msgs\"</em>. But we will get into that later…</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"formats\">Formats<a href=\"#formats\" class=\"hash-link\" aria-label=\"Direct link to Formats\" title=\"Direct link to Formats\">​</a></h2><p>The question that followed was, <em>\"What format do you prefer for changelogs?\"</em> The most popular format by far was <em>Markdown</em>. Its simplicity, readability, and widespread use in the developer community make it highly appealing. Markdown's flexibility in formatting and ease of conversion to other formats also contribute to its popularity. This preference may also indicate its frequent use in blog posts or other articles, as Markdown can be easily rendered.</p><p><em>Plain text</em> files were also a prominent choice. We assume this could be for their simplicity and universal compatibility, making them accessible across various platforms and tools.</p><p>Other notable formats included <em>ReStructuredText</em>, <em>LaTeX</em>, <em>YAML</em>, and <em>blog posts</em>. These formats cater to specific needs, such as enhanced formatting capabilities, structured data representation, or providing more detailed explanations and context. Several unique and creative preferences also emerged, such as <em>Asciidoc</em>, <em>email</em>, and <em>PDFs</em>. This variety of preferences highlights that the needs of different projects and their users vary significantly.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"tools\">Tools<a href=\"#tools\" class=\"hash-link\" aria-label=\"Direct link to Tools\" title=\"Direct link to Tools\">​</a></h2><p>Following the format, we’ve tried to collect tooling (if any) used by the audience to help with the changelog management. People mentioned various text editors, IDEs and of course, <em>chatgpt</em>/<em>ai</em>. But let’s take a look at one specific tool worth sharing:</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"towncrier\">towncrier<a href=\"#towncrier\" class=\"hash-link\" aria-label=\"Direct link to towncrier\" title=\"Direct link to towncrier\">​</a></h3><p>From <a href=\"https://towncrier.readthedocs.io/en/stable/index.html\" target=\"_blank\" rel=\"noopener noreferrer\">the project’s homepage</a>, <em>towncrier delivers the news which is convenient to those that hear it, not those that write it.</em> During a development, <em>\"news fragments\"</em> (~text files) are created and when there is a new release, one can merge those together. Being user-centric and storing the fragments in git (and being able to review) makes it a really interesting choice worth exploring. Sadly, the pre-commit hooks can’t remind you that you’ve forgotten to add a new <em>news fragment</em>. Luckily, there is help in the form of a <a href=\"https://github.com/sanitizers/chronographer-github-app\" target=\"_blank\" rel=\"noopener noreferrer\">Chronographer GitHub application</a> created by <a href=\"https://github.com/webknjaz\" target=\"_blank\" rel=\"noopener noreferrer\">Sviatoslav Sydorenko (@webknjaz)</a> (who was by coincidence also present at the talk)</p><p>Quite interestingly, 11% of the responders mentioned that no automation is used – there is an opportunity for improvement! (But to be fair, it can also mean that someone from the projects wants to prepare something really useful and do this all by hand.)</p><p>There were also some tools like <em>coffee</em>, <em>potato</em>, <em>postal pigeons</em> or <em>beer</em> that we weren’t able to find documentation for. If you find these, let us know so we can add some links...;-)</p><p>There were also various git-based solutions suggested which leads us to the next question:</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"automation-based-on-commit-messages\">Automation based on commit messages<a href=\"#automation-based-on-commit-messages\" class=\"hash-link\" aria-label=\"Direct link to Automation based on commit messages\" title=\"Direct link to Automation based on commit messages\">​</a></h2><p>This is a tricky one, right? It might seem like an obvious choice of getting the input for our changelogs. But… yes, there is a “but”. There are two main reasons why one wants to avoid using commit messages for this:</p><ul><li>Commit messages are meant to be read by developers.</li><li>Commit itself represents a change meaningful for developers, not users.</li></ul><p>Based on these observations, we came up with the following rules in our team (and talk attendees mentioned the same):</p><ul><li>The content of the changelog should be created for users, not developers.</li><li>Changelog should be created for the user-focused level of change =&gt; in our case, pull-request.</li><li>Changelog should be created by the author of the change when the change is being developed.</li></ul><p>Of course, one can still use commits for this, but we don’t think it’s a good idea to have two goals for one text. If you really want to go this way, there is a <a href=\"https://www.conventionalcommits.org/\" target=\"_blank\" rel=\"noopener noreferrer\">Conventional Commits project</a>. If nothing else, it can bring more attention to the commit messages and provide well-defined rules for the project contributors. (Talk attendees also mentioned git-cliff as a changelog generator for <em>Conventional Commits</em>.) You can also use this format independently to user-facing changelog. (Or, maybe as a base info for a human creating the changelog.) To mention also other responses, there were various git-log based solutions mentioned including the functionality provided directly by git-forges.</p><p><img loading=\"lazy\" alt=\"Conventional Commits: search for a user (nothing found)\" src=\"/assets/images/conventional_commits-35ef8be2b4387f5212676cac467c6af2.png\" width=\"1333\" height=\"425\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"packit-blog-post-generator\">Packit blog-post generator<a href=\"#packit-blog-post-generator\" class=\"hash-link\" aria-label=\"Direct link to Packit blog-post generator\" title=\"Direct link to Packit blog-post generator\">​</a></h2><p>As a follow-up to the previous questions, we’ve shown a solution we use in Packit. We researched and tried various solutions but this is what finally works for us:</p><ol><li>When submitting a pull-request, you put your changelog into a pull-request description.</li></ol><p><img loading=\"lazy\" alt=\"Packit workflow 1: pull-request\" src=\"/assets/images/packit_workflow1-35f10086cac60a86bcbb4a80d9addd3f.png\" width=\"1103\" height=\"648\" class=\"img_ev3q\"></p><ol start=\"2\"><li><p>If you forget, a GitHub action will mark the PR red to remind you. (You can also put “N/A” if there is no user-facing change and the PR should be skipped for this check.)</p></li><li><p>There is a GitHub action that we manually trigger when a new release should be prepared – as a result, new pull request is created with the aggregated changelog and version being updated.\nWhen this pull request is merged, the content of the changelog is also put into GitHub release description and from that taken when preparing downstream (i.e. Fedora) updates</p></li></ol><p><img loading=\"lazy\" alt=\"Packit workflow 2: Manual triggering of Github workflow that prepares the changelog\" src=\"/assets/images/packit_workflow2-8bf805ef977f91ba63dcf92ef71715b4.png\" width=\"1219\" height=\"539\" class=\"img_ev3q\">\n<img loading=\"lazy\" alt=\"Packit workflow 3: Content of the pull request created by the workflow\" src=\"/assets/images/packit_workflow3-7beb93a0fe0d14db1816c880e0bc802b.png\" width=\"1596\" height=\"326\" class=\"img_ev3q\">\n<img loading=\"lazy\" alt=\"Packit workflow 4: Published release with the changelog from the pull request\" src=\"/assets/images/packit_workflow4-c0745cfcdcae87a4c5c7132b9926ff74.png\" width=\"1476\" height=\"555\" class=\"img_ev3q\"></p><ol start=\"4\"><li>In Packit, most of our users do not install our packages manually but use our service. When doing a new deployment (by moving stable branches in our repositories), we collect the code snippets and prepare an update post that is published on our project page.</li></ol><p><img loading=\"lazy\" alt=\"Packit workflow 5: Published blog post with changelog from the pull request\" src=\"/assets/images/packit_workflow5-dddf27668b755420ae946f0459e0f3e6.png\" width=\"1149\" height=\"555\" class=\"img_ev3q\"></p><p>Important bit is that in both ways the changelog snippets are used, there is a review in place. So, you can still revisit the text, combine more entries together or remove if this is not relevant to the user after all.</p><p>You can, but don’t need to use the same, but try to think about this, have a discussion within a team. The discussion itself can help you think more about your users.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"nice-changelog-examples\">Nice changelog examples<a href=\"#nice-changelog-examples\" class=\"hash-link\" aria-label=\"Direct link to Nice changelog examples\" title=\"Direct link to Nice changelog examples\">​</a></h2><p>Thanks to our fellow attendees, we can share some examples to be inspired by:</p><ul><li><a href=\"https://github.com/signalapp/Signal-Desktop/releases\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/signalapp/Signal-Desktop/releases</a></li><li><a href=\"https://github.com/packit/packit/blob/main/CHANGELOG.md\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/packit/packit/blob/main/CHANGELOG.md</a> (This wasn’t us who suggested this...;)</li><li><a href=\"https://yarl.aio-libs.org/en/latest/changes/\" target=\"_blank\" rel=\"noopener noreferrer\">https://yarl.aio-libs.org/en/latest/changes/</a></li><li><a href=\"https://github.com/systemd/systemd/releases\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/systemd/systemd/releases</a></li><li><a href=\"https://getgrav.org/#changelog\" target=\"_blank\" rel=\"noopener noreferrer\">https://getgrav.org/#changelog</a> (Nice visualisation!)</li><li><a href=\"https://cockpit-project.org/blog\" target=\"_blank\" rel=\"noopener noreferrer\">https://cockpit-project.org/blog</a> (Yes, blog posts can be used as well!)</li><li><a href=\"https://docs.djangoproject.com/en/5.0/releases/5.0/\" target=\"_blank\" rel=\"noopener noreferrer\">https://docs.djangoproject.com/en/5.0/releases/5.0/</a></li><li><a href=\"https://github.com/ClusterLabs/pcs/blob/main/CHANGELOG.md\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/ClusterLabs/pcs/blob/main/CHANGELOG.md</a></li><li><a href=\"https://qgis.org/en/site/forusers/visualchangelogs.html\" target=\"_blank\" rel=\"noopener noreferrer\">https://qgis.org/en/site/forusers/visualchangelogs.html</a> (Visual changelogs!)</li><li><a href=\"https://github.com/ksh93/ksh/releases\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/ksh93/ksh/releases</a></li><li><a href=\"https://github.com/Hypfer/Valetudo/releases\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/Hypfer/Valetudo/releases</a> (screenshots, breaking changes, personal opinions,...)</li><li><a href=\"https://www.home-assistant.io/blog/categories/release-notes/\" target=\"_blank\" rel=\"noopener noreferrer\">https://www.home-assistant.io/blog/categories/release-notes/</a> (screenshots, a lot of screenshots, deprecations, new plugins,..)</li></ul><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"space-for-improvement\">Space for improvement?<a href=\"#space-for-improvement\" class=\"hash-link\" aria-label=\"Direct link to Space for improvement?\" title=\"Direct link to Space for improvement?\">​</a></h2><p>In addition to preferences, we also sought feedback on potential improvements for managing changelogs. The responses highlighted several key areas where the audience sees opportunities for enhancement:</p><ul><li><strong>AI:</strong> A significant number of responses emphasized the need for AI integration in changelog management, specifically using generative AI for writing changelogs was mentioned.</li><li><strong>Standardization and consistency:</strong> Several responses called for standardizing the format and content of changelogs. Consistency in how changelogs are written and maintained can improve readability and usability. Specific suggestions included using templates and setting ground rules, such as always including issue IDs in commits.</li><li><strong>Automation and integration with development tools:</strong> Improving the automation tools and Integrating changelog generation with existing development tools and CI/CD pipelines was another common suggestion. This could streamline the process, ensuring that changelogs are automatically updated and maintained as part of the development workflow.</li><li><strong>Improving quality:</strong> Improving the quality of changelog messages was a recurring theme. Responses suggested focusing on clear, concise, and meaningful wording and also highlighted the need for changelogs to be more user-oriented rather than developer-centric.</li></ul><p>Several responses addressed specific needs, such as differentiating upstream and downstream changelogs, supporting all CI systems, and referencing the tickets associated with changes. Additionally, there were responses emphasizing the importance of keeping changelogs simple and easy to understand.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"conclusion\">Conclusion<a href=\"#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\">​</a></h2><p>And now what?</p><p>What you can do now? Improve changelog in your project. Get involved in the project you like and help with the changelogs. Read the changelos.</p><p>What we can do together? Let’s collaborate on the tools and share good practices!</p><p>And what about the standardisation? Let’s create a new standard! <a href=\"https://xkcd.com/927/\" target=\"_blank\" rel=\"noopener noreferrer\">https://xkcd.com/927/</a></p><p>With that, let’s quote a response from one of our attendees:\n<em>\"Many more people read the changelog than write it, so it's worth it to put in the effort.\"</em></p><hr><p>This post was also posted at <a href=\"https://medium.com/@laura.barcziova/do-you-like-your-changelogs-what-devconf-cz-attendees-think-771f51a4e3b0\" target=\"_blank\" rel=\"noopener noreferrer\">medium.com</a>.</p>",
            "url": "https://packit.dev/posts/changelogs",
            "title": "Do you like your changelogs? What DevConf.CZ attendees think",
            "summary": "Last month, we had the pleasure of engaging with a dynamic audience during our interactive talk on changelogs at the DevConf in Brno, Czech Republic. In case you missed it, you can watch the recording here. Throughout the session, we explored various aspects of changelog usage, including their content, format, and the potential for automation. By asking a series of questions to the attendees, we gathered insights and opinions that highlighted both common practices and divergent viewpoints within the community. In this follow-up article, we aim to summarise the key findings from our discussion, analyse the trends and preferences that emerged, and offer our reflections on the role of changelogs in software development.",
            "date_modified": "2024-07-01T00:00:00.000Z",
            "author": {
                "name": "František Lachman",
                "url": "https://github.com/lachmanfrantisek"
            },
            "tags": []
        },
        {
            "id": "https://packit.dev/posts/devconf-2024",
            "content_html": "<p>The first part of June is usually quite busy for our team. Why? The last couple of years, this has been a time of <a href=\"https://devconf.cz/\" target=\"_blank\" rel=\"noopener noreferrer\">DevConf.CZ conference</a>. (The unpredictable January had been changed into a more pleasant June.)\nEven though the conference itself is important, it’s used as an opportunity for various people from around the globe to come to Brno and thanks to that, a lot is happening also during the days around.\nFor the Packit team, it’s a nice opportunity to have the whole team together in one place – we can do some fun teambuilding (like canoeing this year) but also discuss any technical topics or meet our users and realise how are the real people behind all the nicknames. This time we also prepared something for them:</p><p><img loading=\"lazy\" alt=\"Packit team at DevConf.CZ\" src=\"/assets/images/team_at_devconf-afb9591ce65a7eec16d0cd6b938dc91f.jpg\" width=\"1625\" height=\"1083\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"packit-workshop\">Packit workshop<a href=\"#packit-workshop\" class=\"hash-link\" aria-label=\"Direct link to Packit workshop\" title=\"Direct link to Packit workshop\">​</a></h2><p>Before DevConf, we recognized a unique opportunity: numerous users and potential users of Packit would be visiting Brno for the conference. Therefore, we decided to organise an in-person workshop with a main focus on our release automation. We had previously organised multiple online runs, for which you can find the materials <a href=\"https://packit.dev/docs/workshops-materials\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>, so we were mostly prepared. This initiative brought both Red Hatters and non-Red Hatters, resulting in a rich exchange of ideas and great feedback. In the end, the workshop served not only for learning about our release automation but also about the CI capabilities of Packit in upstream.</p><p>During the workshop, several key areas of interest emerged:\nBuilding in Sidetags - There was significant interest in building in sidetags. Participants provided valuable feedback on the workflow and configuration that Nikola Forro is currently developing, see <a href=\"https://github.com/packit/packit/issues/1870\" target=\"_blank\" rel=\"noopener noreferrer\">the GitHub issue</a>. One of the discussion points was the automatic resolution of dependencies as the next step for the current static configuration.\nCommon specfile manipulation tasks - Participants expressed a need for ways to handle common specfile manipulation tasks, which could be utilised in <a href=\"https://packit.dev/docs/configuration/actions\" target=\"_blank\" rel=\"noopener noreferrer\">Packit's actions</a> or for debugging purposes. Specific use cases included removing source/patch ranges for Copr builds, replacing sources within specfiles or getting and setting specfile versions. Our <a href=\"https://github.com/packit/specfile\" target=\"_blank\" rel=\"noopener noreferrer\">specfile library</a> already covers some of these, but besides that, also other alternative solutions were proposed, such as creating a CLI specifically for handling these tasks or adding Packit subcommands to facilitate these operations.</p><p>Besides those, in relation to the release automation, some existing issues were brought up, such as the <a href=\"https://github.com/packit/packit/issues/1724\" target=\"_blank\" rel=\"noopener noreferrer\">one</a> about Packit to not create divergent branches when syncing release. Additionally, a bug/inconsistency was directly addressed and fixed during the workshop, see <a href=\"https://github.com/packit/packit/pull/2327\" target=\"_blank\" rel=\"noopener noreferrer\">https://github.com/packit/packit/pull/2327</a> .</p><p>Overall, the workshop was a success and we are happy for our great users for coming! The gained insights will definitely influence the ongoing development and improvement of Packit. We celebrated the successful workshop with a nice lunch together with the participants.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"packit-members-talks\">Packit members talks<a href=\"#packit-members-talks\" class=\"hash-link\" aria-label=\"Direct link to Packit members talks\" title=\"Direct link to Packit members talks\">​</a></h2><p>Of all the various proposals prepared by our team (and there as a lot!), 3 were accepted and we were able to show some interesting topics to the audience.</p><p><img loading=\"lazy\" alt=\"Laura and Franta presenting\" src=\"/assets/images/laura_franta_presenting-ee59e9798e209dc044ce54f8c420fffe.jpg\" width=\"1560\" height=\"1040\" class=\"img_ev3q\"></p><p>The first session was an interactive on hold by Laura and František about changelogs – we used a Mentimer platform to be able to interact with the audience. We could not only collect information what people are interested to see in changelogs or what tooling do they use, but also showed charts from the research Laura made as part of here diploma thesis the last year. As part of the session, we were able to show the changelog automation we use in Packit. There is also <a href=\"https://packit.dev/posts/changelogs\" target=\"_blank\" rel=\"noopener noreferrer\">a blog post</a> covering the talk and all the interesting findings.</p><p>For the next session, František took a bunch of happy (of course..) Packit users and organised a user showcase. In just half an hour 8 people went to stage and provided an introduction to Packit, tmt, Testing Farm and showed 4 interesting usecases. Recording can be found <a href=\"https://www.youtube.com/watch?v=7n8pypmrQh4\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>. Interestingly, the two of the usecases overlayed – Cockpit has introduced their tests-cases into their dependencies to realise issues soon and one of such dependencies is Podman. Both Podman and Cockpit was presented on the stage.</p><p>During the third session, Laura and Tomáš showed our journey to team role rotation and how we do this these days. They used Mentimer as well as for the changelog one so it was a great fun. Missed it? No worries, there is no only a <a href=\"https://www.youtube.com/watch?v=y1t7Wd31bL8\" target=\"_blank\" rel=\"noopener noreferrer\">recording</a>, but also <a href=\"https://packit.dev/agile/weekly-roles\" target=\"_blank\" rel=\"noopener noreferrer\">a blog-post serie</a> covering this topic. <a href=\"https://medium.com/@laura.barcziova/role-rotation-tutorial-957ed3545ef2\" target=\"_blank\" rel=\"noopener noreferrer\">The last part</a> helps you do the same, and as usual, we have this automated…</p><p><img loading=\"lazy\" alt=\"Laura and Tomáš presenting\" src=\"/assets/images/laura_and_tomas_presenting-6ab4883c30d4bd9790065a7d139b388f.jpg\" width=\"1625\" height=\"1083\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"talks-related-to-packit\">Talks related to Packit<a href=\"#talks-related-to-packit\" class=\"hash-link\" aria-label=\"Direct link to Talks related to Packit\" title=\"Direct link to Talks related to Packit\">​</a></h2><p>Even though some of our talk proposals were not accepted this year, our users represented us very well. In addition to the previously mentioned user showcase), there were two other dedicated talks by Packit users:</p><ul><li><strong>Shifting Left in Podman with Copr, Packit, and TMT</strong> - In this talk, Mohan Boddu described how they utilise Packit, Copr, and TMT to shift their testing setup and test early in the process. This talk also included a short live demo. (<a href=\"https://pretalx.com/devconf-cz-2024/talk/WVNJZS/\" target=\"_blank\" rel=\"noopener noreferrer\">https://pretalx.com/devconf-cz-2024/talk/WVNJZS/</a>)</li><li><strong>Upstream Cross-Project Testing: Never Break Your API Consumers</strong> - In this talk, Martin Pitt from the Cockpit team described the use case of reverse dependency testing (<a href=\"https://packit.dev/docs/cross-project-testing\" target=\"_blank\" rel=\"noopener noreferrer\">https://packit.dev/docs/cross-project-testing</a>) using Packit. (<a href=\"https://pretalx.com/devconf-cz-2024/talk/KDZZES/\" target=\"_blank\" rel=\"noopener noreferrer\">https://pretalx.com/devconf-cz-2024/talk/KDZZES/</a>)</li></ul><p>Additionally, Siteshwar Vashisht presented about OpenScanHub, a service for static analysis of Linux distributions, where he also mentioned Packit and <a href=\"https://github.com/packit/packit-service/issues/2107\" target=\"_blank\" rel=\"noopener noreferrer\">our plans</a> for integration (<a href=\"https://pretalx.com/devconf-cz-2024/talk/7C38GJ/\" target=\"_blank\" rel=\"noopener noreferrer\">https://pretalx.com/devconf-cz-2024/talk/7C38GJ/</a>).</p><hr><p>So, that was it. A DevConf week we enjoy being part of same as enjoying it being over.</p><p><img loading=\"lazy\" alt=\"Team at a photo booth\" src=\"/assets/images/team_booth-f1e93b6716011b1243e6b6d2251432c5.jpg\" width=\"1472\" height=\"982\" class=\"img_ev3q\"></p>",
            "url": "https://packit.dev/posts/devconf-2024",
            "title": "DevConf.CZ 2024 and week around for Packit",
            "summary": "The first part of June is usually quite busy for our team. Why? The last couple of years, this has been a time of DevConf.CZ conference. (The unpredictable January had been changed into a more pleasant June.)",
            "date_modified": "2024-07-01T00:00:00.000Z",
            "author": {
                "name": "František Lachman",
                "url": "https://github.com/lachmanfrantisek"
            },
            "tags": []
        },
        {
            "id": "https://packit.dev/posts/aws-and-image-builder",
            "content_html": "<p>Have you ever wanted to bring your pull request changes in a cloud image easily?\nCurious about how easy it can be? With Packit, it can be just about commenting on your pull request with <code>/packit vm-image-build</code>.</p><p>With the above command, Packit automates all the manual steps needed to create an\nRPM package with your pull request changes and asks the Image Builder to install it\ninside a brand new cloud image.\nLet's have a look at the prerequisites for this.</p><h1>Join the Red Hat Developer Program</h1><p>If you don't already have a business account you can create a\n<em>Red Hat Developer account</em> at no cost <a href=\"https://developers.redhat.com/about\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>.</p><p>You need a subscription in order to use the\n<a href=\"https://console.redhat.com/insights/image-builder\" target=\"_blank\" rel=\"noopener noreferrer\">Image Builder service</a>\nand launch the builded images in the <a href=\"https://aws.amazon.com/console/\" target=\"_blank\" rel=\"noopener noreferrer\">AWS management console</a>.</p><h1>Prepare to upload AWS AMI images</h1><p>Before uploading an AWS AMI image, you must configure the AWS system for receiving them.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"prerequisites\">Prerequisites<a href=\"#prerequisites\" class=\"hash-link\" aria-label=\"Direct link to Prerequisites\" title=\"Direct link to Prerequisites\">​</a></h3><ul><li>You must have an Access Key ID configured in the <a href=\"https://aws.amazon.com/iam/\" target=\"_blank\" rel=\"noopener noreferrer\">AWS IAM account manager</a>.</li><li>You must have a writable <a href=\"https://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html\" target=\"_blank\" rel=\"noopener noreferrer\">S3 bucket</a> prepared.</li></ul><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"procedure\">Procedure<a href=\"#procedure\" class=\"hash-link\" aria-label=\"Direct link to Procedure\" title=\"Direct link to Procedure\">​</a></h3><p>Follow <a href=\"https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/composing_a_customized_rhel_system_image/creating-cloud-images-with-composer_composing-a-customized-rhel-system-image#preparing-for-uploading-aws-ami-images_creating-cloud-images-with-composer\" target=\"_blank\" rel=\"noopener noreferrer\">these steps</a>\nto satisfy the above prerequisites.</p><h1>The manual steps</h1><p>Are you wondering what are the manual steps for bringing your pull request changes\nin a cloud image and why you should automate them?</p><p>There could be many ways to achieve this goal but let's see together the closest to our\nautomated solution. Below you can find a summary of all the needed manual steps;\nI am quite sure after reading them, you will want to automate them with Packit!</p><ul><li><p>Build an RPM package with your pull request changes through <strong>COPR</strong>, go to <a href=\"https://copr.fedorainfracloud.org\" target=\"_blank\" rel=\"noopener noreferrer\">https://copr.fedorainfracloud.org</a></p><ol><li>Install <code>copr-cli</code>.</li><li>Create your account and service token.</li><li>Add your token to `~/.config/copr.</li><li>Create a new COPR project.</li><li>Start a build with your local pull request changes using <code>copr-cli</code>.</li><li><strong>WAIT for the build to finish</strong>.</li></ol></li><li><p>Create a new cloud image through the <strong>Image Builder console</strong>, go to <a href=\"https://console.redhat.com/insights/image-builder\" target=\"_blank\" rel=\"noopener noreferrer\">https://console.redhat.com/insights/image-builder</a>\n7. Login with your <em>Red Hat developer</em> account.\n8. Click on the <code>Create Image</code> button, choose <em>AWS image</em> type and follow the wizard.\n9. <strong>WAIT for the build to finish</strong>.\n10. Open the <code>Launch</code> link for the builded image.</p></li><li><p>Launch and access the AWS image through the <strong>AWS management console</strong>, go to <a href=\"https://aws.amazon.com/console/\" target=\"_blank\" rel=\"noopener noreferrer\">https://aws.amazon.com/console/</a>\n11. The previous link will open an AWS console tab with the\n<em>Launch an Instance</em> wizard preset to use the builded image.\nYou need to login into the <em>AWS management console</em> using an <em>AWS Account ID</em>\nallowed to access the <em>AMI Image</em> you just created.\n12. Select a <strong>Key pair</strong>, or create one if you don't have it already,\nto be able to ssh the image later.\n13. Click on <code>Launch Instance</code>\n14. Connect to instance using an ssh client\n15. Add the previously created COPR repo to the list of available dnf repositories.\n16. Install the package you have created at step number 4.\n17. Now you are ready to test your code in a real cloud image.</p></li></ul><p>For every new pull request you want to test directly in a cloud image you have to repeat\nsteps 4-16 or automate them through Packit!</p><h1>Automate the steps</h1><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"install-packit\">Install Packit<a href=\"#install-packit\" class=\"hash-link\" aria-label=\"Direct link to Install Packit\" title=\"Direct link to Install Packit\">​</a></h2><p>Installing Packit is pretty straightforward.</p><ol><li>Create a valid <a href=\"https://fedoraproject.org/wiki/Account_System\" target=\"_blank\" rel=\"noopener noreferrer\">Fedora Account System (FAS)</a>\naccount (if you don't already have one).\nWhy do you need it? After these few steps you will start building (and potentially shipping)\nFedora packages through the <a href=\"https://copr.fedorainfracloud.org/\" target=\"_blank\" rel=\"noopener noreferrer\">COPR service</a> and we need you to agree with the Fedora license.</li><li>Install our GitHub application on <a href=\"https://github.com/marketplace/packit-as-a-service\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub Marketplace</a>,\nor <a href=\"https://packit.dev/docs/guide/#how-to-set-up-packit-on-gitlab\" target=\"_blank\" rel=\"noopener noreferrer\">configure a webhook</a> on GitLab\n(depending on where your project lives).</li><li>Make Packit <a href=\"https://packit.dev/docs/guide/#2-approval\" target=\"_blank\" rel=\"noopener noreferrer\">approve your FAS username</a>;\non Github the approval process is automated and for Gitlab you have to contact us.</li></ol><p>Now you are ready to automate the process as described below.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"setup-packit\">Setup Packit<a href=\"#setup-packit\" class=\"hash-link\" aria-label=\"Direct link to Setup Packit\" title=\"Direct link to Setup Packit\">​</a></h2><p>Create a <code>.packit.yaml</code> configuration file in your pull request.</p><p>But just the first time! After your pull request has been merged, Packit will take the <code>.packit.yaml</code> file from the target <em>main branch</em>.</p><p>The configuration file will look like the following:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">---</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">jobs:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- job: copr_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  trigger: pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  targets:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  - fedora-all</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- job: vm_image_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  trigger: pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  image_request:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    architecture: x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    image_type: aws</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    upload_request:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      type: aws</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      options:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        share_with_accounts:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        - &lt; shared-aws-account-id &gt;</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  image_distribution: fedora-39</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  copr_chroot: fedora-39-x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  image_customizations:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    packages: [hello-world]</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"copr_build-job\">copr_build job<a href=\"#copr_build-job\" class=\"hash-link\" aria-label=\"Direct link to copr_build job\" title=\"Direct link to copr_build job\">​</a></h3><p>The first job tells Packit service to build an RPM package, for the Fedora release you want,\nin this example all the active fedora releases, and to add your pull request changes to the package.</p><p>To further customize the COPR builds made by Packit you may want to give a look at this\n<a href=\"https://packit.dev/docs/configuration/upstream/copr_build\" target=\"_blank\" rel=\"noopener noreferrer\">guide</a>.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"vm_image_build-job\">vm_image_build job<a href=\"#vm_image_build-job\" class=\"hash-link\" aria-label=\"Direct link to vm_image_build job\" title=\"Direct link to vm_image_build job\">​</a></h3><p>The second job tells Packit how to configure the Builder Image service.</p><p>The first two lines of this job are still meant for Packit;\nthey allow Packit to react to your pull request comment <code>/packit vm-image-build</code>.\nPackit does not build a VM image automatically, as it does when it builds a COPR package,\nto save you from no wanted costs.</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">- job: vm_image_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">trigger: pull_request</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>The other lines are meant to customize the Image Builder behaviour.</p><p>You are asking to build an <em>AWS</em> image, with a <em>fedora-39</em> distribution,\nfor the <em>x86_64</em> architecture and you want to share it with the listed\n<em>AWS Account IDs</em>.</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">image_request:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  architecture: x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  image_type: aws</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  upload_request:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    type: aws</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    options:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      share_with_accounts:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      - &lt; shared-aws-account-id &gt;</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">image_distribution: fedora-39</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>You don't want to manually install the COPR package into the image,\nfor this reason you ask the Image Builder to install it (<em>hello-world</em>).</p><p>You tell Image Builder to take it from the COPR chroot <em>fedora-39-x86_64</em>,\nand you don't need to create or specify a COPR project because it has\nbeen automatically created by Packit for you.</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">copr_chroot: fedora-39-x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">image_customizations:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  packages: [hello-world]</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"create-comment-and-test-a-pull-request\">Create, comment and test a pull request!<a href=\"#create-comment-and-test-a-pull-request\" class=\"hash-link\" aria-label=\"Direct link to Create, comment and test a pull request!\" title=\"Direct link to Create, comment and test a pull request!\">​</a></h2><p>Create a pull request, mine will show you the <strong>world</strong> word in green 🌿.</p><p>You are ready to go, just comment your pull request with</p><p><code>/packit vm-image-build</code></p><p>and the image will be built and customized for you.</p><p>Look for the check named <strong>vm-image-build-fedora-39-x86_64</strong>\nand wait for it to finish.</p><p><img loading=\"lazy\" alt=\"Wait for check vm-image-build-fedora-39-x86_64 to finish\" src=\"/assets/images/checks_vm_image_build-0ec652132670f4da590dca9dc372a468.png\" width=\"512\" height=\"194\" class=\"img_ev3q\"></p><p>Open its details and you will find the link\nto the AWS image.</p><p><img loading=\"lazy\" alt=\"The check details have a link to the AWS image\" src=\"/assets/images/link_to_aws_image-16f87362483365f8530c80041de39ada.png\" width=\"512\" height=\"198\" class=\"img_ev3q\"></p><p>Open the AWS link (you need to be already logged in) and\nsee the details of your image ready to be launched.</p><p><img loading=\"lazy\" alt=\"The AWS image details\" src=\"/assets/images/ami-link-2bb9d9e9a1da6c8e18ca31b39db13789.png\" width=\"512\" height=\"246\" class=\"img_ev3q\"></p><p>Launch your image instance and connect to it.</p><p><img loading=\"lazy\" alt=\"Connect to instance details\" src=\"/assets/images/connect-to-instance-0f2ae4856b17566477e3e4e29074075f.png\" width=\"512\" height=\"393\" class=\"img_ev3q\"></p><p>Test it!</p><p><img loading=\"lazy\" alt=\"Test it!\" src=\"/assets/images/hello-world-809c7da500a4aca0a1d5b7fbdd3ea1fc.png\" width=\"495\" height=\"94\" class=\"img_ev3q\"></p>",
            "url": "https://packit.dev/posts/aws-and-image-builder",
            "title": "Customize AWS cloud images with Image Builder and Packit",
            "summary": "Have you ever wanted to bring your pull request changes in a cloud image easily?",
            "date_modified": "2024-01-22T00:00:00.000Z",
            "author": {
                "name": "Maja Massarini",
                "url": "https://github.com/majamassarini"
            },
            "tags": [
                "image-builder"
            ]
        },
        {
            "id": "https://packit.dev/posts/specfile-introduction",
            "content_html": "<p>Have you ever wanted to make changes in an RPM spec file programmatically? <em>specfile</em> library\nhas been created for that very purpose. It is a pure Python library that allows you to conveniently\nedit different parts of a spec file while doing its best to keep the resulting changeset minimal\n(no unnecessary whitespace changes etc.).</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"installation\">Installation<a href=\"#installation\" class=\"hash-link\" aria-label=\"Direct link to Installation\" title=\"Direct link to Installation\">​</a></h2><p>The library is packaged for Fedora, EPEL 9 and EPEL 8 and you can simply install it with dnf:</p><div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">dnf </span><span class=\"token function\" style=\"color:#d73a49\">install</span><span class=\"token plain\"> python3-specfile</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>On other systems, you can use pip (just note that it requires RPM Python bindings to be installed):</p><div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">pip </span><span class=\"token function\" style=\"color:#d73a49\">install</span><span class=\"token plain\"> specfile</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"usage\">Usage<a href=\"#usage\" class=\"hash-link\" aria-label=\"Direct link to Usage\" title=\"Direct link to Usage\">​</a></h2><p>Let's have a look at a few simple examples of how to use the library.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"bumping-release\">Bumping release<a href=\"#bumping-release\" class=\"hash-link\" aria-label=\"Direct link to Bumping release\" title=\"Direct link to Bumping release\">​</a></h3><p>To bump release and add a new changelog entry, we could use the following code:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">from</span><span class=\"token plain\"> specfile </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> Specfile</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> spec</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">release </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token builtin\">str</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token builtin\">int</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">expanded_release</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">+</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">add_changelog_entry</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"- Bumped release for test purposes\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>Let's take a look at what happens here:</p><p>We instantiate <code>Specfile</code> class with a path to our spec file and use it as a context manager\nto automatically save all changes upon exiting the context.</p><p>We then use <code>expanded_release</code> property to get the current value of <code>Release</code> tag after macro expansion.\nWe assume it is numeric, so we simply convert it to integer, add 1, convert the result back to string\nand assign the new value to <code>release</code> property.</p><div class=\"theme-admonition theme-admonition-tip alert alert--success admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>tip</div><div class=\"admonitionContent_S0QG\"><p>Note that <code>release</code>/<code>expanded_release</code> properties exclude dist tag (usually <code>%{?dist}</code>) - for convenience,\nit is ignored when reading and preserved unmodified when writing. If that's not what you want, you can use\n<code>raw_release</code>/<code>expanded_raw_release</code> properties instead.</p></div></div><p>Finally, we add a new changelog entry. We don't specify any other arguments but content,\nso the author is determined automatically using the same procedure as <code>rpmdev-packager</code> uses\nand date is set to current day.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"switching-to-autochangelog\">Switching to <code>%autochangelog</code><a href=\"#switching-to-autochangelog\" class=\"hash-link\" aria-label=\"Direct link to switching-to-autochangelog\" title=\"Direct link to switching-to-autochangelog\">​</a></h3><p>To make a switch from traditional changelog to <code>%autochangelog</code>, we could do the following:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> pathlib</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">from</span><span class=\"token plain\"> specfile </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> Specfile</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> autosave</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token boolean\" style=\"color:#36acaa\">True</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">sections</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> sections</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    entries </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> sections</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">changelog</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    sections</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">changelog</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"%autochangelog\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">pathlib</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">Path</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"changelog\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">write_text</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"\\n\"</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">join</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">entries</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">+</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"\\n\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>Let's take a look at what happens here:</p><p>We instantiate <code>Specfile</code> class with a path to our spec file and we also set <code>autosave</code> argument\nthat ensures that any changes are saved automatically as soon as possible.</p><p><em>specfile</em> heavily relies on context managers. Here we are using <code>sections()</code> method that returns\na context manager that we can use to manipulate spec file sections. Upon exiting the context,\nany modifications done are propagated to the internal representation stored in our <code>Specfile</code> instance,\nand since <code>autosave</code> is set, they are immediately saved to the spec file as well.</p><p>First, we store a copy of the content of the <code>%changelog</code> section. The content is represented\nas a list of lines.</p><p>Then we replace the content with a single line - \"%autochangelog\".</p><p>Finally, we save the stored content into a \"changelog\" file.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"iterating-through-tags\">Iterating through tags<a href=\"#iterating-through-tags\" class=\"hash-link\" aria-label=\"Direct link to Iterating through tags\" title=\"Direct link to Iterating through tags\">​</a></h3><p>Contexts can be nested. Here is a code that iterates through all <em>package</em> sections\n(including the first, implicitly named one; also known as <em>preamble</em>) and prints expanded value\nof all <code>Requires</code> tags:</p><div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">spec </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> Specfile</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"example.spec\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">sections</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> sections</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">for</span><span class=\"token plain\"> section </span><span class=\"token keyword\" style=\"color:#00009f\">in</span><span class=\"token plain\"> sections</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># normalized name of a section is lowercased</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> section</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">normalized_name </span><span class=\"token operator\" style=\"color:#393A34\">!=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"package\"</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword\" style=\"color:#00009f\">continue</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:#00009f\">with</span><span class=\"token plain\"> spec</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">tags</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">section</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">as</span><span class=\"token plain\"> tags</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword\" style=\"color:#00009f\">for</span><span class=\"token plain\"> tag </span><span class=\"token keyword\" style=\"color:#00009f\">in</span><span class=\"token plain\"> tags</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># normalized name of a tag is capitalized</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token keyword\" style=\"color:#00009f\">if</span><span class=\"token plain\"> tag</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">normalized_name </span><span class=\"token operator\" style=\"color:#393A34\">!=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Requires\"</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                    </span><span class=\"token keyword\" style=\"color:#00009f\">continue</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token keyword\" style=\"color:#00009f\">print</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string-interpolation string\" style=\"color:#e3116c\">f\"Section: </span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">{</span><span class=\"token string-interpolation interpolation\">section</span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">.</span><span class=\"token string-interpolation interpolation builtin\">id</span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">}</span><span class=\"token string-interpolation string\" style=\"color:#e3116c\">, Tag: </span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">{</span><span class=\"token string-interpolation interpolation\">tag</span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">.</span><span class=\"token string-interpolation interpolation\">name</span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">}</span><span class=\"token string-interpolation string\" style=\"color:#e3116c\">, Value: </span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">{</span><span class=\"token string-interpolation interpolation\">tag</span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">.</span><span class=\"token string-interpolation interpolation\">expanded_value</span><span class=\"token string-interpolation interpolation punctuation\" style=\"color:#393A34\">}</span><span class=\"token string-interpolation string\" style=\"color:#e3116c\">\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>Let's take a look at what happens here:</p><p>We instantiate <code>Specfile</code> class with a path to our spec file. This time we don't set <code>autosave</code> because\nwe are not doing any modifications (though we could still save any changes explicitly using <code>save()</code> method).</p><p>Then we use <code>sections()</code> context manager and iterate through sections; we skip sections not called \"package\"\n(the initial <em>%</em> is ommited for convenience).</p><p>After that we use <code>tags()</code> context manager and pass the current section as an argument. This allows us\nto iterate through tags in the current section. Without any argument, we would get a list of tags in <em>preamble</em>,\nthe very first section in a spec file. We skip tags not called \"Requires\" and finally print the values\nof <code>Requires</code> tags after macro expansion. We also print tag names (not normalized) and section IDs - those are\nsection names followed by options, e.g. \"package -n alternative-name-for-example\".</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"more-info-and-links\">More info and links<a href=\"#more-info-and-links\" class=\"hash-link\" aria-label=\"Direct link to More info and links\" title=\"Direct link to More info and links\">​</a></h2><p>Are you interested in more details, trying the library out or even contributing? You can find <em>specfile</em> source code on <a href=\"https://github.com/packit/specfile\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub</a>.\nSee the <a href=\"https://github.com/packit/specfile/blob/main/README.md\" target=\"_blank\" rel=\"noopener noreferrer\">README</a> for more tips and usage examples.\nYou can also check out the <a href=\"https://packit.dev/specfile/api/specfile\" target=\"_blank\" rel=\"noopener noreferrer\">API reference</a>.</p>",
            "url": "https://packit.dev/posts/specfile-introduction",
            "title": "Introduction to specfile library",
            "summary": "Have you ever wanted to make changes in an RPM spec file programmatically? specfile library",
            "date_modified": "2024-01-12T00:00:00.000Z",
            "author": {
                "name": "Nikola Forró",
                "url": "https://github.com/nforro"
            },
            "tags": [
                "specfile"
            ]
        },
        {
            "id": "https://packit.dev/posts/experiences_with_rust",
            "content_html": "<p>\"How absurdly simple!\" I cried.</p><p>\"Quite so!\" said he, a little nettled. \"Every problem becomes very childish when once it is explained to you.\"</p><ul><li>Arthur Conan Doyle, \"The Adventure of the Dancing Men\"</li></ul><p>We have planned for a while to use Packit to generate packages on Copr\non demand for our somewhat complicated Rust executable, stratisd. It\nlooked like this was going to be challenging, and in a sense it was,\nbut once the task was completed, it turned out to have been pretty\nstraightforward.</p><p>The two primary parts of our Stratis project are stratisd, a big,\nfairly complicated Rust project which generates multiple distinct Rust\nexecutables and also installs scripts and configuration files and so\nforth, and stratis-cli, a relatively simple Python project which\ncommunicates with stratisd over the D-Bus. Our main purpose in getting\non-demand packages of both these projects was not to test the\npackaging, although that is a nice thing to do, but to have a\nconvenient way to do functional testing of the project, frequently\ngenerating a stratisd package from one stratisd pull request and a\nstratis-cli package from a matching stratis-cli pull request.</p><p>The Packit team had already obliged us by preparing a Packit\nconfiguration file for our stratis-cli repo, we thus merely had to\nfigure out how to do the same for stratisd. We already had some\nscripts which we could run by hand to make the SRPMs for both projects\nso that we could manually send them to Copr so, as it turned out, all\nwe really needed to do was figure out how to write a Packit\nconfiguration file for stratisd so that Packit would do these tasks\nfor us. There follows a quick summary of the decisions we made to\nsolve this problem. Note that our whole and only task was to figure\nout how to create the source artifacts and edit the spec file and\nto provide these in such a way that Packit could take over from there,\nbuild the SRPM, and carry on to request the Copr builds which provide\nthe binary packages for testing.</p><p>A Packit configuration is used to set certain configuration <em>options</em>,\nto override certain <em>actions</em>, or to define certain <em>hooks</em>. The\navailable actions and hooks are specific to a given job or set of jobs.\nIf an action is not\noverridden in a project's Packit configuration, Packit will execute\nits own default action. For example, Packit's default for the\ncreate-archive action is just git-archive. Any action can be overridden by\nspecifying a sequence of commands. For the stratisd Packit\nconfiguration, we found that we had to override the majority of the\nactions.</p><p>Note that the <a href=\"https://github.com/stratis-storage/stratisd/blob/master/.packit.yaml\" target=\"_blank\" rel=\"noopener noreferrer\">stratisd Packit configuration file</a> is quite\nsimple as most of the action is in the <code>create_archive.py</code> script. Some\nthings to make note of are the following:</p><ol><li><p><code>merge_pr_in_ci</code> is set to false. This prevents Packit from\nautomatically merging our pull request into its target branch. It has\nalways been our custom to build from the unmerged branch when testing\nPRs and we preferred to do the same in our Packit configuration.</p></li><li><p><code>fix-spec-file</code> contains a dummy echo action. This is how we override\nPackit's default spec file editing action. Instead of specifying an\noverride for this action, we use <a href=\"https://github.com/stratis-storage/ci/blob/master/release_management/create_artifacts.py\" target=\"_blank\" rel=\"noopener noreferrer\">our own script</a>, <code>create_artifacts.py</code>, to\nedit the spec file as well as to generate the three source artifacts that we\nuse in this package in the <code>create-archive</code> action.</p></li><li><p><code>create_artifacts.py</code> uses the Packit team's <a href=\"https://github.com/packit/specfile\" target=\"_blank\" rel=\"noopener noreferrer\">specfile package</a> to\nedit the stratisd specfile. We needed just two modifications: 1. To overwrite the Version field with our preferred version string. 2. To overwrite the Source entries with the names and paths of the\nsource artifacts.\nThis requires just one <a href=\"https://github.com/stratis-storage/ci/blob/master/release_management/_utils.py#L80\" target=\"_blank\" rel=\"noopener noreferrer\">very simple function</a> using specfile.</p></li><li><p>In the Packit configuration, the <code>update_release</code> field is set to\nfalse. We prefer to update the Version field in the spec file using\nour <code>create_archive.py</code> script, so that the updated version is\nrecognized as a pre-release version of our current version by\n<code>rpmdev-vercmp</code>.</p></li><li><p>We modified our <a href=\"https://github.com/stratis-storage/stratis-cli/blob/master/.packit.yaml\" target=\"_blank\" rel=\"noopener noreferrer\">stratis-cli Packit configuration file</a> to work the\nsame way as our stratisd one.</p></li></ol><p>In summary, we got the ability to take advantage of the Packit\ninfrastructure for Copr builds by figuring out how to satisfy its\nrequirements for the source artifacts and the specfile. Note that our\ndecisions about how to do this were made based on the scripts we had\nalready written to generate the SRPMs and the particular requirements\nof our project. For example, our release scripts are written in\nPython, and we stuck with that choice. That turned out to be handy,\nbecause that allowed us to use the specfile project in our scripts to\nedit the spec file. But it would have been possible to write the\nartifact creation script in Rust using the cargo xtask pattern just as\nwell, and to solve the spec file rewriting problem using, e.g., sed.\nWe overwrote the Version field in the spec file, rather than allowing\nPackit to autobump our release number, because our development process\nrequires us to bump the version in the Cargo.toml (for Rust) and\nsetup.cfg (for Python) files to the version we will release as soon as\nwe begin development. These choices and their implementations could be\nmade differently to support a project with different constraints and\ndifferent existing infrastructure.</p>",
            "url": "https://packit.dev/posts/experiences_with_rust",
            "title": "Experiences using Packit for a Rust executable Project",
            "summary": "\"How absurdly simple!\" I cried.",
            "date_modified": "2023-10-10T00:00:00.000Z",
            "author": {
                "name": "mulhern",
                "url": "https://github.com/mulkieran"
            },
            "tags": []
        },
        {
            "id": "https://packit.dev/posts/verify-sync-release-volunteers",
            "content_html": "<p>In the upcoming months, we plan to migrate our service to a new cluster. However, this may affect <code>propose_downstream</code>\nand <code>pull_from_upstream</code> jobs due to the new firewall rules. The problematic aspects could be:</p><ul><li>commands you run in your <code>actions</code> during syncing the release involving interactions with external servers</li><li>downloading your sources from various hosting services (crates.io, npm, gems, etc.)</li></ul><p>To smoothen this transition, we kindly encourage you to enable one of these jobs on our already migrated staging instance.\nThis recommendation is particularly important if you belong to one of the groups affected by the two previous points.\nThis proactive step will help us identify and address any issues promptly.</p><p>Both instances can be run at the same time and the behaviour can be configured via the <code>packit_instances</code> configuration key,\nwhich is by default set to <code>[\"prod\"]</code>. Picking just one instance is required only for <code>koji_build</code> and <code>bodhi_update</code> jobs since\nboth instances work with the production instances of Fedora systems. To avoid too much noise in your dist-git PRs, you\nmay enable the <code>pull_from_upstream</code>/<code>propose_downstream</code> job for only one target, resulting in only one additional PR created.</p><p>Here's how you can enable one of the jobs on the staging instance:</p><ul><li><code>pull-from-upstream</code>:\nThe only thing needed is to duplicate the job in your Packit config using <code>packit_instances</code> configuration option. Example:</li></ul><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pull_from_upstream</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> release</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">packit_instances</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"stg\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">dist_git_branches</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">rawhide</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><ul><li><code>propose-downstream</code>:\nFor this job, you first need to <a href=\"/docs/guide#staging-instance\">enable our staging Github app</a>\n(you should be already automatically approved if you had been previously approved for production instance).\nAfter that, similarly to <code>pull-from-upstream</code>, you only need to duplicate the job in your Packit config using <code>packit_instances</code>. Example:</li></ul><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> propose_downstream</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> release</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">packit_instances</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"stg\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">dist_git_branches</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">rawhide</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><div class=\"theme-admonition theme-admonition-info alert alert--info admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z\"></path></svg></span>info</div><div class=\"admonitionContent_S0QG\"><p>When merging the PRs created by Packit, please don't forget to merge the PRs created by the production instance\nif you have a follow-up <code>koji_build</code> job enabled to ensure your builds will not be skipped\n(or you can allow builds for staging instance as well, see <a href=\"/docs/configuration/downstream/koji_build#optional-parameters\">allowed_pr_authors</a>)).</p></div></div><p>We would be happy if you could then report any problems to <a href=\"#contact\">us</a>. We appreciate your collaboration in ensuring a seamless migration. Your Packit team!</p>",
            "url": "https://packit.dev/posts/verify-sync-release-volunteers",
            "title": "Call for volunteers: help to test us the release syncing using staging instance",
            "summary": "In the upcoming months, we plan to migrate our service to a new cluster. However, this may affect propose_downstream",
            "date_modified": "2023-09-05T12:46:18.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "downstream",
                "pull-from-upstream",
                "propose-downstream",
                "staging"
            ]
        },
        {
            "id": "https://packit.dev/posts/manual-triggering",
            "content_html": "<p>Recently, we received multiple contributions from the Strimzi team, specifically <a href=\"https://github.com/Frawless\" target=\"_blank\" rel=\"noopener noreferrer\">Jakub Stejskal</a>\nand <a href=\"https://github.com/kornys\" target=\"_blank\" rel=\"noopener noreferrer\">David Kornel</a>,\nfor the functionality of manual triggering of jobs and other related improvements, mostly focusing on the testing\nUX. We are very happy about these and would like to showcase the results of their awesome contributions.</p><p>Strimzi team wanted to onboard Packit to ease their testing in pull requests, but they have had multiple test suites that could run\nfor a long time, and they did not want to run all of the test suites for each new commit in a pull request.</p><p>Let's now look together at what they implemented to solve their usecase.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"manual-only-triggering-of-jobs\">Manual-only triggering of jobs<a href=\"#manual-only-triggering-of-jobs\" class=\"hash-link\" aria-label=\"Direct link to Manual-only triggering of jobs\" title=\"Direct link to Manual-only triggering of jobs\">​</a></h2><p>Firstly, a new configuration option <a href=\"/docs/configuration/jobs#manual_trigger\"><code>manual_trigger</code></a> was introduced.\nWith this new configuration option, users can enable triggering Packit jobs only manually and avoid specified jobs being\nautomatically triggered when, e.g., a new commit arrives to a pull request.\nThe only thing needed to make this work is to add <code>manual_trigger: true</code> to the job's definition:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> tests</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">targets</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> centos</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">stream</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">9</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">skip_build</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">manual_trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>This new configuration option allows saving resources and running builds or tests, e.g. only when the pull request is ready for\ntesting and can be especially useful for projects having huge test plans.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"triggering-test-jobs-based-on-labels-and-identifiers\">Triggering test jobs based on labels and identifiers<a href=\"#triggering-test-jobs-based-on-labels-and-identifiers\" class=\"hash-link\" aria-label=\"Direct link to Triggering test jobs based on labels and identifiers\" title=\"Direct link to Triggering test jobs based on labels and identifiers\">​</a></h2><p>The above solution is very easy to use; however, there might be use cases where the users don’t want to trigger all the jobs.\nA particular example could be running a smoke test job before running the sanity one.</p><p>To solve this, for the test jobs, Jakub and David introduced 2 new ways to trigger a specific job.</p><p>The first one is to trigger the job based on the configured <a href=\"/docs/configuration/upstream/tests#optional-parameters\"><code>identifier</code></a>. To trigger a test job with <code>identifier: regression-operators</code> in the\njob configuration, the Packit comment command will be:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">/packit test --identifier regression-operators</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>That command will execute the job with this specific identifier, nothing else.</p><p>And what if someone wants to execute more than one job? Users can easily use multiple identifiers in a comma-separated list:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">/packit test --identifier regression-operators,regression-components</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>But specifying a longer list of identifiers every time might get a little bit annoying,\nespecially when the identifiers are usually used together repeatedly.</p><p>To improve the UX, there was introduced <a href=\"/docs/configuration/upstream/tests#optional-parameters\"><code>labels</code></a> configuration field that can group together multiple jobs.\nEach job can contain a list of <code>labels</code> in their definition:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> tests</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">identifier</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> regression</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">operators</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">targets</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> centos</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">stream</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">9</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">skip_build</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">manual_trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">labels</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> regression</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> sanity</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> tests</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">identifier</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> regression</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">components</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">targets</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> centos</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">stream</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">9</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">skip_build</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">manual_trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">labels</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> regression</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> tests</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">identifier</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> acceptance</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">operators</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">targets</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> centos</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">stream</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">9</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">skip_build</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">manual_trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">labels</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> acceptance</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> sanity</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>With this, one can comment</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">/packit test --labels regression</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>and the comment will trigger all jobs that contain <code>regression</code> in the list of labels in the job configuration.\nIt is again also possible to specify a comma-separated list of labels:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">/packit test --labels regression,sanity</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"conclusion\">Conclusion<a href=\"#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\">​</a></h2><p>As already mentioned, these improvements were made as contributions from outside of the Packit team, and it was such\na nice experience to collaborate with someone new! And this brings us to a reminder:\nAnyone can contribute! So if you are missing some features, feel free to open a pull request, and we will gladly help\nyou so that your feature can land in our production!</p>",
            "url": "https://packit.dev/posts/manual-triggering",
            "title": "(Tests) job triggering improvements",
            "summary": "Recently, we received multiple contributions from the Strimzi team, specifically Jakub Stejskal",
            "date_modified": "2023-07-11T06:46:18.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "configuration"
            ]
        },
        {
            "id": "https://packit.dev/posts/monorepos",
            "content_html": "<p>We are very happy to announce a major enhancement to Packit! We have now added support for\nmonorepositories, enabling the integration of upstream repositories containing multiple downstream packages.\nIf you have a repository in the monorepo format, Packit can now help you automate the integration to downstream\ndistributions both from CLI and as a service.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"configuration\">Configuration<a href=\"#configuration\" class=\"hash-link\" aria-label=\"Direct link to Configuration\" title=\"Direct link to Configuration\">​</a></h2><p>Let's take a look at how a monorepository should be configured so that Packit can automate the process!</p><p>The main addition to the Packit configuration file in the context of monorepositories are the keys\n<a href=\"/docs/configuration#packages\"><code>packages</code></a> and <a href=\"/docs/configuration#paths\"><code>paths</code></a>.</p><p><code>packages</code> holds a dictionary of <code>{package_name: package_configuration}</code> where package configuration can contain any keys\nthat were previously used as top-level keys for the standard (single) package configuration. The <code>paths</code> can be defined\nin each <code>package_configuration</code> and should hold a list of paths that should be considered for the particular package.</p><p>The <code>packages</code> section in the configuration can then look like this:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token key atrule\" style=\"color:#00a4db\">packages</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">python-copr</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">downstream_package_name</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> python</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">copr</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">upstream_package_name</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">paths</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> ./python</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">specfile_path</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> python</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">copr.spec</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">files_to_sync</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> python</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">copr.spec</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">copr-cli</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">downstream_package_name</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">cli</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">upstream_package_name</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">cli</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">paths</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> ./cli</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">specfile_path</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">cli.spec</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">files_to_sync</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">cli.spec</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">copr-backend</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">downstream_package_name</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">backend</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">upstream_package_name</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">backend</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">paths</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> ./backend</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">specfile_path</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">backend.spec</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">files_to_sync</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">backend.spec</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>That was the configuration of the packages and their locations in general, but how should these values then be utilised?</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"packit-service-support\">Packit Service support<a href=\"#packit-service-support\" class=\"hash-link\" aria-label=\"Direct link to Packit Service support\" title=\"Direct link to Packit Service support\">​</a></h3><p>For the Packit Service jobs, there is one more addition to the configuration: the <a href=\"/docs/configuration/jobs#packages\"><code>packages</code></a> key again,\nthat can be used in each job and tells which packages should be considered for that particular job.</p><p>As a result, the repository in monorepo format could have jobs in the Packit configuration configured like this:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token key atrule\" style=\"color:#00a4db\">jobs</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">packages</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">backend</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> copr</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">cli</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">targets</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">all</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">preserve_project</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">True</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> copr_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">packages</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> python</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">copr</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">targets</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">all</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">x86_64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">all</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">aarch64</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">manual_trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">True</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>And the commit statuses in GitHub/GitLab will also include the name of the package:\n<img loading=\"lazy\" alt=\"Monorepo statuses\" src=\"/assets/images/statuses-8048b69ec99393dd77aaace7258dffff.png\" width=\"879\" height=\"516\" class=\"img_ev3q\"></p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"cli-support\">CLI support<a href=\"#cli-support\" class=\"hash-link\" aria-label=\"Direct link to CLI support\" title=\"Direct link to CLI support\">​</a></h3><p>As for the CLI, you can now for each command specify the <code>-p</code> or <code>--packages</code> argument followed by the package name\nand the scope of the command will take into consideration only the specified packages:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">packit build in-mock --package my-package-1 --package my-package-2</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"wrapping-up\">Wrapping up<a href=\"#wrapping-up\" class=\"hash-link\" aria-label=\"Direct link to Wrapping up\" title=\"Direct link to Wrapping up\">​</a></h2><p>If you have a repository in the monorepo format, give it a try now and share your feedback with us!</p><p>Going forward, we are about to implement the <a href=\"https://github.com/packit/packit-service/issues/2105\" target=\"_blank\" rel=\"noopener noreferrer\">possibility of defining dependencies between jobs</a>,\nallowing for even greater flexibility and control of monorepository jobs.</p><p>We are also happy to help with any contributions from the community to help us expand and refine the support with additional functionalities,\nsuch as <a href=\"https://github.com/packit/packit-service/issues/2006\" target=\"_blank\" rel=\"noopener noreferrer\">being able to define paths the service should react to</a>\nor <a href=\"https://github.com/packit/packit/issues/1925\" target=\"_blank\" rel=\"noopener noreferrer\">templating features</a>.</p>",
            "url": "https://packit.dev/posts/monorepos",
            "title": "Introducing monorepository support",
            "summary": "We are very happy to announce a major enhancement to Packit! We have now added support for",
            "date_modified": "2023-07-04T07:20:06.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "monorepos"
            ]
        },
        {
            "id": "https://packit.dev/posts/release-field-handling",
            "content_html": "<p>We have recently made some fixes to the process of handling the <code>Release</code> field regarding the <code>%autorelease</code> macro, so let's take that opportunity to explain how it works.</p><p>You can maintain the <code>Release</code> field manually, you can use a dummy value or you can take advantage of the <code>%autorelease</code> macro.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"maintaining-release-manually\">Maintaining <code>Release</code> manually<a href=\"#maintaining-release-manually\" class=\"hash-link\" aria-label=\"Direct link to maintaining-release-manually\" title=\"Direct link to maintaining-release-manually\">​</a></h3><p>You can maintain the <code>Release</code> field manually as you would do downstream, for example you could bump the value every time you make changes to the spec file and reset it to <em>1</em> when you release a new version.</p><p>Packit will not touch the value unless it detects a change in <code>Version</code> and no change in <code>Release</code>. In such case it will reset <code>Release</code> to <em>1</em> in the dist-git spec file, to ensure that the resulting NVR is not higher than any existing NVR in dist-git (that could have been already created by <code>propose_downstream</code> in a different branch for example).</p><p>You most likely want to enable the <code>sync_changelog</code> option so that your upstream <code>%changelog</code> is synchronized to dist-git as well.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"using-a-dummy-value\">Using a dummy value<a href=\"#using-a-dummy-value\" class=\"hash-link\" aria-label=\"Direct link to Using a dummy value\" title=\"Direct link to Using a dummy value\">​</a></h3><p>You can use a value like <em>0</em> or <em>1</em> and never touch it, Packit will make sure it is set to <em>1</em> in the dist-git spec file.\nYou can do this if you don't care about upstream <code>%changelog</code>, i.e. you have <code>sync_changelog</code> disabled and use <code>copy_upstream_release_description</code> or the <code>changelog-entry</code> action to generate it downstream.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"using-autorelease\">Using <code>%autorelease</code><a href=\"#using-autorelease\" class=\"hash-link\" aria-label=\"Direct link to using-autorelease\" title=\"Direct link to using-autorelease\">​</a></h3><p>You can use the <code>%autorelease</code> macro in the <code>Release</code> field and the <code>%autochangelog</code> macro in <code>%changelog</code>. In this case Packit will not change anything, it will only synchronize changes made to the arguments of the macro (if any).</p><p>If you want to start using <code>%autorelease</code> and <code>%autochangelog</code>, you should <a href=\"https://docs.pagure.org/fedora-infra.rpmautospec/opting-in.html\" target=\"_blank\" rel=\"noopener noreferrer\">do the change</a> in dist-git before releasing a new version upstream and triggering <code>propose_downstream</code> job, otherwise Packit will continue to set <code>Release</code> to <em>1</em> in the dist-git spec file.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"autorelease-in-dist-git\"><code>%autorelease</code> in dist-git<a href=\"#autorelease-in-dist-git\" class=\"hash-link\" aria-label=\"Direct link to autorelease-in-dist-git\" title=\"Direct link to autorelease-in-dist-git\">​</a></h2><p>No matter how you maintain the <code>Release</code> field in your upstream spec file, Packit will never overwrite the <code>%autorelease</code> macro if it is used in the dist-git spec file.</p>",
            "url": "https://packit.dev/posts/release-field-handling",
            "title": "Handling of Release field in propose_downstream job",
            "summary": "We have recently made some fixes to the process of handling the Release field regarding the %autorelease macro, so let's take that opportunity to explain how it works.",
            "date_modified": "2023-05-23T12:00:00.000Z",
            "author": {
                "name": "Nikola Forró",
                "url": "https://github.com/nforro"
            },
            "tags": [
                "specfile",
                "propose-downstream"
            ]
        },
        {
            "id": "https://packit.dev/posts/pre-commit-hooks",
            "content_html": "<p><a href=\"https://pre-commit.com\" target=\"_blank\" rel=\"noopener noreferrer\">pre-commit</a> is a wonderful tool that saves you\na lot of time by automatically checking your changes before you\ncommit and/or push them out.</p><p>For example, in our <a href=\"https://github.com/packit/packit/blob/main/.pre-commit-config.yaml\" target=\"_blank\" rel=\"noopener noreferrer\">packit repo</a>\nwe run various hooks upon each commit:</p><ul><li><a href=\"https://github.com/psf/black\" target=\"_blank\" rel=\"noopener noreferrer\">Black (Python code formatter)</a>,</li><li><a href=\"https://github.com/prettier/prettier\" target=\"_blank\" rel=\"noopener noreferrer\">Prettier (code formatter)</a>,</li><li><a href=\"https://pypi.org/project/flake8\" target=\"_blank\" rel=\"noopener noreferrer\">Flake8 (Python source code checker)</a>,</li><li><a href=\"https://github.com/python/mypy\" target=\"_blank\" rel=\"noopener noreferrer\">Mypy (static type checker for Python)</a>,</li><li>and <a href=\"https://github.com/pre-commit/pre-commit-hooks\" target=\"_blank\" rel=\"noopener noreferrer\">several other pre-commit hooks</a>.</li></ul><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"our-pre-commit-hooks\">Our pre-commit hooks<a href=\"#our-pre-commit-hooks\" class=\"hash-link\" aria-label=\"Direct link to Our pre-commit hooks\" title=\"Direct link to Our pre-commit hooks\">​</a></h2><p><a href=\"https://github.com/packit/pre-commit-hooks\" target=\"_blank\" rel=\"noopener noreferrer\">We also have a few hooks</a>\nwhich we've created and which you might find useful as well.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"check-rebase\">check-rebase<a href=\"#check-rebase\" class=\"hash-link\" aria-label=\"Direct link to check-rebase\" title=\"Direct link to check-rebase\">​</a></h3><p>We in Packit love linear git history.\nThis hook checks whether your branch is up-to-date with the upstream,\nand we use it to know when it's time to rebase changes before we push them.</p><p>To try, add this to your <code>.pre-commit-config.yaml</code></p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">repo</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> https</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\">//github.com/packit/pre</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">commit</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">hooks</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">rev</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> v1.2.0</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">hooks</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">id</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> check</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">rebase</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token key atrule\" style=\"color:#00a4db\">args</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">upstream_url</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"validate-config\">validate-config<a href=\"#validate-config\" class=\"hash-link\" aria-label=\"Direct link to validate-config\" title=\"Direct link to validate-config\">​</a></h3><p>Packit uses a <a href=\"https://packit.dev/docs/configuration\" target=\"_blank\" rel=\"noopener noreferrer\">YAML configuration file</a>\nin an upstream repository.\nWe have a <a href=\"https://packit.dev/docs/cli/config/validate\" target=\"_blank\" rel=\"noopener noreferrer\">packit config validate</a> command\nto check it, but it's easy to forget (to run it) and notice a typo after you\ncommitted and pushed the changes and waited for some time for Packit to tell you\nthat in a PR.</p><p>It's much faster to catch the problem before committing and/or pushing the changes.</p><h4 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"validate-config-in-container\">validate-config-in-container<a href=\"#validate-config-in-container\" class=\"hash-link\" aria-label=\"Direct link to validate-config-in-container\" title=\"Direct link to validate-config-in-container\">​</a></h4><p>This hook runs (only if there's been a change in the <code>.packit.yaml</code>)\n<code>packit</code> in a container (from <a href=\"https://quay.io/repository/packit/packit\" target=\"_blank\" rel=\"noopener noreferrer\">our image</a>),\nmounts your sources inside and runs the <code>packit config validate</code>.</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">repo</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> https</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\">//github.com/packit/pre</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">commit</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">hooks</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">rev</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> v1.2.0</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">hooks</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">id</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> validate</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">config</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">in</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">container</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>It requires docker/podman, which can be a problem for example in a\n<a href=\"https://github.com/pre-commit-ci/issues/issues/11\" target=\"_blank\" rel=\"noopener noreferrer\">CI</a>.</p><h4 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"validate-config-1\">validate-config<a href=\"#validate-config-1\" class=\"hash-link\" aria-label=\"Direct link to validate-config\" title=\"Direct link to validate-config\">​</a></h4><p>Another option is a hook which runs the <code>packit</code> binary directly installed\non the machine. If there's no <code>packit</code>, the hook passes to not break\nfor example your CI where <code>packit</code> is most likely not installed.</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">repo</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> https</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\">//github.com/packit/pre</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">commit</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">hooks</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">rev</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> v1.2.0</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">hooks</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">id</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> validate</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">config</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h5 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"but-why-the-hook-doesnt-install-packit-itself\">But why the hook doesn't install <code>packit</code> itself?<a href=\"#but-why-the-hook-doesnt-install-packit-itself\" class=\"hash-link\" aria-label=\"Direct link to but-why-the-hook-doesnt-install-packit-itself\" title=\"Direct link to but-why-the-hook-doesnt-install-packit-itself\">​</a></h5><p>Right, typically, when you run a pre-commit hook for the first time,\nit installs everything it needs.\nLike in case of Python, pre-commit <code>pip</code> installs all the dependencies.</p><p>The problem in our case is that <code>packit</code> has a lot of dependencies and\nsome of them (if missing) are compiled from source when you try to\n<a href=\"https://packit.dev/docs/cli/#from-pypi\" target=\"_blank\" rel=\"noopener noreferrer\">pip install packit</a>.\nThat needs <code>gcc</code> and additional <code>devel</code> packages\nto be installed on the machine prior to running the hook for the first time.\nThat would make the hook usage very user unfriendly, leaving aside that\nsometimes (in a CI) you don't have access to the machine to install them\nprior to running the hooks.</p>",
            "url": "https://packit.dev/posts/pre-commit-hooks",
            "title": "Packit's pre-commit hooks",
            "summary": "pre-commit is a wonderful tool that saves you",
            "date_modified": "2023-05-16T11:00:00.000Z",
            "author": {
                "name": "Jiří Popelka",
                "url": "https://github.com/jpopelka"
            },
            "tags": [
                "workflow"
            ]
        },
        {
            "id": "https://packit.dev/posts/2022-features",
            "content_html": "<p>As you will see in the following paragraphs, the year 2022 was really fruitful for the Packit project. Without further ado, let’s take a look at what the Packit team accomplished last year!</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"fedora-automation\">Fedora automation<a href=\"#fedora-automation\" class=\"hash-link\" aria-label=\"Direct link to Fedora automation\" title=\"Direct link to Fedora automation\">​</a></h2><p>We have made a huge improvement in downstream automation. At the beginning of the year, we <a href=\"https://packit.dev/posts/downstream-automation/\" target=\"_blank\" rel=\"noopener noreferrer\">finished the workflow</a> and you are now able to use Packit to get your release from upstream via dist-git and Koji to Bodhi. As usual, you can pick just what you need. This workflow consists of three jobs:</p><ul><li><code>propose-downstream</code>: as a reaction to an upstream release, the source archive is saved to a lookaside cache, specfile is updated and sent as a pull request to Fedora dist-git.</li><li><code>koji-build</code>: as a reaction to a new dist-git commit, a new Koji build is triggered (you can specify allowed authors of a commit or merged pull request).</li><li><code>bodhi-update</code>: as a reaction to a successfully finished Koji build, a new Bodhi update is created</li></ul><p><img loading=\"lazy\" alt=\"Detail of a Bodhi update created by Packit\" src=\"/assets/images/bodhi-update-b24d047f5572831c4ad8de446cf81148.png\" width=\"851\" height=\"477\" class=\"img_ev3q\"></p><p>But that wasn’t all. At the very end of the year, the Packit team implemented an alternative to the <code>propose-downstream</code> job that we call <code>pull-from-upstream</code>. The logic of the job is the very same: the source archive is saved to a lookaside cache, specfile is updated and sent as a pull request to Fedora dist-git. The only – and main – difference is that the job is defined downstream (in the default dist-git branch, <code>rawhide</code> or its <code>main</code> alias) so you don’t need to install Packit in the upstream repository. The information about a new release is received from the <a href=\"https://docs.fedoraproject.org/en-US/package-maintainers/Upstream_Release_Monitoring\" target=\"_blank\" rel=\"noopener noreferrer\">Upstream Release Monitoring</a>. The <code>pull-from-upstream</code> job is mainly targeted to the Fedora maintainers without upstream access or with upstream not being supported by Packit. (This job works with any upstream using git.) The setup is nicely described in <a href=\"https://packit.dev/posts/pull-from-upstream\" target=\"_blank\" rel=\"noopener noreferrer\">this blog post</a>. And if you want a dedicated documentation page for the Fedora downstream automation, look at <a href=\"https://packit.dev/docs/fedora-releases-guide/\" target=\"_blank\" rel=\"noopener noreferrer\">https://packit.dev/docs/fedora-releases-guide/</a>.</p><p><img loading=\"lazy\" alt=\"Pull request created by a pull-from-upstream workflow\" src=\"/assets/images/pull-from-upstream-75eca73c81b62ad029f0c029f0b4e557.png\" width=\"1089\" height=\"886\" class=\"img_ev3q\"></p><p>And that’s still not all, we’ve also added <code>propose-downstream</code> to <a href=\"https://dashboard.packit.dev\" target=\"_blank\" rel=\"noopener noreferrer\">our dashboard</a>. You can now the jobs in <a href=\"https://dashboard.packit.dev/pipelines\" target=\"_blank\" rel=\"noopener noreferrer\">the Pipelines view</a>. Also, logs can be checked on a detail page (that can be accessed from a status of a release commit).</p><p><img loading=\"lazy\" alt=\"Propose downstream result page\" src=\"/assets/images/propose-downstream-result-page-a2d517abb0153c630f4f03b2ad8ccda5.png\" width=\"887\" height=\"617\" class=\"img_ev3q\"></p><p>Still not convinced we’ve done a lot? When using various downstream jobs, you can still hit an issue now and then. (Messages from Fedora infrastructure can get lost or some intermittent error can occur.) Packit automatically retries to overcome temporary issues, but sometimes it’s not enough or there is a real problem that needs to be fixed elsewhere. We can’t resolve the real problems for you, but we can help let you retry the job when needed. And you have two places where to do that.</p><p>As you might be used to with the <code>propose-downstream</code> job, you can use comments in an upstream issue to retrigger Bodhi updates and Koji builds as well. Just configure <a href=\"https://packit.dev/docs/configuration/#issue_repository\" target=\"_blank\" rel=\"noopener noreferrer\"><code>issue_repository</code></a> so Packit knows where to create issues in case of problems. (This does not need to be an upstream issue and this repository can be used for multiple projects.) Alternatively, if you use dist-git pull requests (either made by Packit or other maintainers), you can use a pull request comment to retrigger Koji Build or Bodhi update.</p><p><img loading=\"lazy\" alt=\"Comment to recreate a Bodhi update\" src=\"/assets/images/dist-git-pull-request-comment-61dc300ce80bfec8c7ec5dd2baf20c92.png\" width=\"735\" height=\"510\" class=\"img_ev3q\"></p><p>If you are interested in what Packit has done for its users, you can take a look at the activity of the <code>packit</code> (or <code>packit-stg</code>) FAS user in <a href=\"https://src.fedoraproject.org/user/packit\" target=\"_blank\" rel=\"noopener noreferrer\">dist-git</a>, <a href=\"https://koji.fedoraproject.org/koji/userinfo?userID=4641\" target=\"_blank\" rel=\"noopener noreferrer\">Koji</a> or <a href=\"https://bodhi.fedoraproject.org/users/packit\" target=\"_blank\" rel=\"noopener noreferrer\">Bodhi</a>.</p><p><img loading=\"lazy\" alt=\"Dist-git activity of Packit user\" src=\"/assets/images/packit-dist-git-activity-b6d823fb44b606593470d5657524a98d.png\" width=\"1105\" height=\"389\" class=\"img_ev3q\">\n<img loading=\"lazy\" alt=\"Koji builds triggered by Packit user\" src=\"/assets/images/packit-koji-builds-24b249549037f0d79822c9e851211e09.png\" width=\"1087\" height=\"374\" class=\"img_ev3q\">\n<img loading=\"lazy\" alt=\"Bodhi updates created by Packit user\" src=\"/assets/images/packit-bodhi-updates-all-5b9ac688507f64dafe5284c5e9c7a4a9.png\" width=\"1126\" height=\"327\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"srpm-in-copr\">SRPM in Copr<a href=\"#srpm-in-copr\" class=\"hash-link\" aria-label=\"Direct link to SRPM in Copr\" title=\"Direct link to SRPM in Copr\">​</a></h2><p>Throughout the 2022 we have implemented support for building SRPMs in the Copr and slowly started introducing newly-onboarded projects to use Copr right from the start. The definitive switch to Copr has been done at the beginning of 2023. For more details, take a look at the <a href=\"https://packit.dev/posts/copr-srpms/\" target=\"_blank\" rel=\"noopener noreferrer\">relevant blog post</a>, but let’s shortly describe the benefits:\nMost importantly, you can now use <a href=\"https://packit.dev/docs/configuration/#srpm_build_deps\" target=\"_blank\" rel=\"noopener noreferrer\"><code>srpm_build_deps</code></a> config option to specify the dependencies needed for the build. With the <a href=\"https://github.com/packit/sandcastle\" target=\"_blank\" rel=\"noopener noreferrer\">old solution</a>, this process was manual, global and had to be done by Packit maintainers. Another advantage of being able to use Copr for SRPM builds is access to the SRPM artifacts.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"self-mapping-of-fas-account\">Self-mapping of FAS account<a href=\"#self-mapping-of-fas-account\" class=\"hash-link\" aria-label=\"Direct link to Self-mapping of FAS account\" title=\"Direct link to Self-mapping of FAS account\">​</a></h2><p>From the beginning of the Packit project, for every Packit GitHub installation, we have required a Fedora account so we can be sure, that we are safe to use Fedora systems (like Copr or dist-git) on behalf of that user. Since we automate various tasks for you, we’ve made it possible for you to perform this yourself. (Thanks to the user config field in the Fedora Account System.)\nIf you are interested in how this works, take a look at the blog post we’ve prepared for you: <a href=\"https://packit.dev/posts/fas-verification-automation/\" target=\"_blank\" rel=\"noopener noreferrer\">https://packit.dev/posts/fas-verification-automation/</a></p><p>If you wonder why we check permissions for the installation, we have good news for you. This year, we plan to improve the permission schema, do the checks for each job, and require only what is needed. But more about the plans for 2023 later.</p><p><img loading=\"lazy\" alt=\"Self-mapping process in an issue\" src=\"/assets/images/verify-fas-355a7111420aea52229c20f33a86322c.png\" width=\"932\" height=\"397\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"multiple-project-test-runs\">Multiple-project test runs<a href=\"#multiple-project-test-runs\" class=\"hash-link\" aria-label=\"Direct link to Multiple-project test runs\" title=\"Direct link to Multiple-project test runs\">​</a></h2><p>If you have multiple connected projects (as we do) and work on a feature spanning more of them, the following feature might come in handy. You can use a commit command with a reference to the other pull request and Packit will use Copr builds from both pull requests during the tests. Want to know more? Check this blog post: <a href=\"https://packit.dev/posts/testing-farm-triggering/\" target=\"_blank\" rel=\"noopener noreferrer\">https://packit.dev/posts/testing-farm-triggering/</a></p><p><img loading=\"lazy\" alt=\"Test with external build\" src=\"/assets/images/test-for-external-build-90b12f4f5294499b998234a477d6dbd8.png\" width=\"923\" height=\"884\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"specfile-library\">Specfile library<a href=\"#specfile-library\" class=\"hash-link\" aria-label=\"Direct link to Specfile library\" title=\"Direct link to Specfile library\">​</a></h2><p>This one might not be relevant to most of our users, but we would still like to announce, that we’ve created <a href=\"https://github.com/packit/specfile\" target=\"_blank\" rel=\"noopener noreferrer\">a Python library</a> for specfile manipulation. It can not only parse various weird spec files but also can edit them with as little diff as possible. Also, the code is really interesting so check it out. Now, it’s used by Packit and <a href=\"https://github.com/rebase-helper/rebase-helper\" target=\"_blank\" rel=\"noopener noreferrer\">rebase-helper</a> and you can watch <a href=\"https://www.youtube.com/watch?v=yzMfBPdFXZY&amp;t=17s\" target=\"_blank\" rel=\"noopener noreferrer\">this demo</a> if you want to know more.\nIn case you’ve missed that, this is not the first time we’ve extracted a part of our codebase for wider usage – another nice example is a <a href=\"https://github.com/packit/ogr/\" target=\"_blank\" rel=\"noopener noreferrer\">forge-independent Python library for GitHub/GitLab/Pagure API called OGR</a>.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"vm-image-builds\">VM Image Builds<a href=\"#vm-image-builds\" class=\"hash-link\" aria-label=\"Direct link to VM Image Builds\" title=\"Direct link to VM Image Builds\">​</a></h2><p>Having Copr builds available for your pull-requests is really nice, but you can now have VM image builds as well. It would be really wasteful to do this for each and every commit so we decided to trigger this by a <code>/packit vm-image-build </code> comment. Similarly to other jobs, Packit uses an external system to do the hard work. This feature is possible thanks to the <a href=\"https://console.redhat.com/insights/image-builder\" target=\"_blank\" rel=\"noopener noreferrer\">Red Hat Image Builder</a>. This feature is a fresh start on this journey and we are investigating the possibilities of Packit in this field. Check <a href=\"https://packit.dev/docs/configuration/upstream/vm_image_build\" target=\"_blank\" rel=\"noopener noreferrer\">our documentation</a> and let us know what you think.</p><p><img loading=\"lazy\" alt=\"VM image build as a result of the comment\" src=\"/assets/images/vm-image-build-9778abe48e8d422ff8863368f4df2930.png\" width=\"1103\" height=\"820\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"plans-for-the-next-year\">Plans for the next year<a href=\"#plans-for-the-next-year\" class=\"hash-link\" aria-label=\"Direct link to Plans for the next year\" title=\"Direct link to Plans for the next year\">​</a></h2><p>Do you wonder what we plan for you for the year 2023? That is not a secret. For some time, we have been opening our planning and since the last year, you can check our <a href=\"https://github.com/orgs/packit/projects/7/\" target=\"_blank\" rel=\"noopener noreferrer\">Kanban board</a> since it has become the primary place we use on daily bases. (It used to be half-manually and half-automatically synced.)\nEvery quarter, our team sits down and discusses our plans for the next three months. We use MOSCOW (=MUST x SHOULD x COULD x WON’T) prioritisation method to group and compare all of our epics. The result of this time’s planning can be seen <a href=\"https://github.com/orgs/packit/projects/7/views/25\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>.</p><p>Do you want to know how we decide and how you can influence us? It’s pretty easy. Firstly, we need to know about a bug or feature request. Secondly, the task needs to be worth the work. (And should be related to our mission.) We can’t work on everything so we need to pick the work with a bigger impact (a lot of projects will benefit from that or a significant benefit for a smaller group). So shortly, if you want something to be done: create an issue, provide a clear reasoning why we should do that and find other projects that can benefit from that.</p><p>And also, our project is open source. We are more than happy to help anyone contribute to our code base!</p><hr><p>With that, I, personally, would like to thank all of the Packit team members for their outstanding work during the year. And I also would like to thank you, our users, for using our project, being kind, helpful and patient! I wish you all a happy new year and less mundane work as possible!</p><p>On behalf of the Packit team,\nFrantišek</p>",
            "url": "https://packit.dev/posts/2022-features",
            "title": "2022 for Packit",
            "summary": "As you will see in the following paragraphs, the year 2022 was really fruitful for the Packit project. Without further ado, let’s take a look at what the Packit team accomplished last year!",
            "date_modified": "2023-01-28T10:58:50.000Z",
            "author": {
                "name": "František Lachman",
                "url": "https://github.com/lachmanfrantisek"
            },
            "tags": [
                "2022",
                "yearly-features",
                "summary"
            ]
        },
        {
            "id": "https://packit.dev/posts/pull-from-upstream",
            "content_html": "<p>In the previous year, we <a href=\"/posts/downstream-automation\">automated</a> the Fedora downstream release process in Packit.\nThe first step of the release process, propagating the upstream release to Fedora,\nis covered by the <a href=\"/docs/configuration/upstream/propose_downstream\"><code>propose_downstream</code></a> job.\nThis job updates the sources in Fedora, the spec file, and other needed files and creates pull requests with the changes\nin the dist-git repository.</p><p>The downside of this job is that for its execution, users need to install Packit Service GitHub/GitLab\napp since this job reacts only to GitHub/GitLab release webhooks.\nHowever, the person who maintains the package in Fedora may not be the upstream maintainer and may not have admin access\nto the upstream GitHub/GitLab repository.</p><p>To cover this case, we came up with a new job called <code>pull_from_upstream</code>, which aims to update Fedora dist-git similarly\nto <code>propose_downstream</code>, but is configured directly in the dist-git repository.\nLet's now look at how to set it up and how it works.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"setup\">Setup<a href=\"#setup\" class=\"hash-link\" aria-label=\"Direct link to Setup\" title=\"Direct link to Setup\">​</a></h2><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"upstream-release-monitoring\">Upstream release monitoring<a href=\"#upstream-release-monitoring\" class=\"hash-link\" aria-label=\"Direct link to Upstream release monitoring\" title=\"Direct link to Upstream release monitoring\">​</a></h3><p><code>pull_from_upstream</code> job reacts to a new bug in <a href=\"https://bugzilla.redhat.com/\" target=\"_blank\" rel=\"noopener noreferrer\">Bugzilla</a> about a new upstream version\nof a project. The bug is automatically created by\n<a href=\"https://docs.fedoraproject.org/en-US/package-maintainers/Upstream_Release_Monitoring/\" target=\"_blank\" rel=\"noopener noreferrer\">Upstream Release Monitoring</a>.\nTo enable the Upstream Release Monitoring:</p><ol><li><p>Add the upstream project (if it is not there yet)\nto <a href=\"https://release-monitoring.org/\" target=\"_blank\" rel=\"noopener noreferrer\">Anitya</a> and configure the mapping to a Fedora package:\n<img loading=\"lazy\" alt=\"Project in Anitya\" src=\"/assets/images/anitya-project-895fdf4a3840fb0f008e6e004219b65e.png\" width=\"598\" height=\"705\" class=\"img_ev3q\"></p></li><li><p>Enable the monitoring in the dist-git repository (<a href=\"https://src.fedoraproject.org\" target=\"_blank\" rel=\"noopener noreferrer\">Fedora Package Sources</a>):</p></li></ol><p><img loading=\"lazy\" alt=\"Monitoring in dist-git\" src=\"/assets/images/dist-git-monitoring-072d1b24827060d7f1818cc11c3e47df.png\" width=\"539\" height=\"521\" class=\"img_ev3q\"></p><div class=\"theme-admonition theme-admonition-info alert alert--info admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 14 16\"><path fill-rule=\"evenodd\" d=\"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z\"></path></svg></span>info</div><div class=\"admonitionContent_S0QG\"><p>In Anitya, there are multiple backends you can configure the mapping for.\nBesides GitHub or GitLab, you can use e.g. PyPI, pagure, or\n<a href=\"https://release-monitoring.org/static/docs/user-guide.html#backends\" target=\"_blank\" rel=\"noopener noreferrer\">many others</a>.\nAlso, be aware that there can be a delay in retrieving the new version,\nso the update to Fedora is usually not created instantly (e.g. for Python projects,\nit is better to configure PyPI backend rather than GitHub since the monitoring\nthere is much less delayed).</p></div></div><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"packit-configuration\">Packit configuration<a href=\"#packit-configuration\" class=\"hash-link\" aria-label=\"Direct link to Packit configuration\" title=\"Direct link to Packit configuration\">​</a></h3><p>To automatically pull the upstream release as a reaction to the bug in Bugzilla, <code>pull_from_upstream</code> job\nneeds to be defined in the default branch\n(<code>rawhide</code>) of the dist-git repository in the Packit configuration file (see\n<a href=\"/docs/configuration/downstream/pull_from_upstream\">our documentation</a>). The <a href=\"/docs/configuration#upstream_project_url\"><code>upstream_project_url</code></a>\nneeds to be a URL pointing to a Git repository so that we can do <code>git</code> commands on it.\nIf not specified, upstream repository is not being cloned.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"pull_from_upstream-in-action\"><code>pull_from_upstream</code> in action<a href=\"#pull_from_upstream-in-action\" class=\"hash-link\" aria-label=\"Direct link to pull_from_upstream-in-action\" title=\"Direct link to pull_from_upstream-in-action\">​</a></h2><p>Let's showcase the new job in action for the latest release of\n<a href=\"https://pypi.org/project/packitos/\" target=\"_blank\" rel=\"noopener noreferrer\">Packit itself</a>.</p><p>As you can see in the <code>Setup</code> section above, the Upstream Release Monitoring is configured:\nthere is a PyPI project <code>packitos</code> in Anitya\nwith configured mapping to the Fedora package <code>packit</code> and the monitoring in the\n<a href=\"https://src.fedoraproject.org/rpms/packit\" target=\"_blank\" rel=\"noopener noreferrer\"><code>packit</code> dist-git repository</a> is enabled.\nWe could configure the mapping in Anitya from the GitHub project directly instead, and it would work as well. Just be aware that\nfor each Fedora package, there can be a mapping only from one project.</p><p>In Packit configuration file, we have configured the job and related options:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token key atrule\" style=\"color:#00a4db\">upstream_project_url</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> https</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\">//github.com/packit/packit</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">issue_repository</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> https</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\">//github.com/packit/packit</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">copy_upstream_release_description</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">jobs</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pull_from_upstream</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> release</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">dist_git_branches</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">all</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> epel</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token number\" style=\"color:#36acaa\">8</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>You can see that version <code>0.66.0</code> of Packit (<code>packitos</code> in PyPI) was released:</p><p><img loading=\"lazy\" alt=\"Packit release PyPI\" src=\"/assets/images/packit-release-pypi-d9a9d2675c7d4349e41b296190e10665.png\" width=\"1128\" height=\"456\" class=\"img_ev3q\"></p><p>When Upstream Release Monitoring retrieved this new version, it created a new bug:</p><p><img loading=\"lazy\" alt=\"Bugzilla\" src=\"/assets/images/packit-release-bugzilla-2b6ecea0deabb2e89a2c4e57838bfca8.png\" width=\"448\" height=\"179\" class=\"img_ev3q\"></p><p>This triggered Packit, and after checking the Packit configuration in dist-git\nand finding the <code>pull_from_upstream</code> job, this job was run.</p><p>Using the <code>upstream_project_url</code> from the configuration, Packit was able to get the needed information\nfrom the corresponding GitHub release:\n<img loading=\"lazy\" alt=\"Packit release GitHub\" src=\"/assets/images/packit-gh-release-8041fa5c1f87fee966813e716db076f1.png\" width=\"1142\" height=\"645\" class=\"img_ev3q\"></p><p>As a result, pull requests for configured branches were created.\nHere is an example of one of the created pull requests and part of its content:\n<img loading=\"lazy\" alt=\"Dist-git PR\" src=\"/assets/images/pull-from-upstream-pr-084101cf1b0cbbefbf0797ef6638c0d8.png\" width=\"743\" height=\"323\" class=\"img_ev3q\">\n<img loading=\"lazy\" alt=\"Pull request content\" src=\"/assets/images/pull-from-upstream-content-1465ffb64bb623bf4bda8d5accef38d0.png\" width=\"1110\" height=\"950\" class=\"img_ev3q\"></p><p>Since we have configured the <a href=\"/docs/configuration#issue_repository\"><code>issue_repository</code></a>, we could be\nalso notified about errors:\n<img loading=\"lazy\" alt=\"Pull from upstream issue\" src=\"/assets/images/pull-from-upstream-issue-0699d8c149066d81d53dd2318043eabc.png\" width=\"930\" height=\"474\" class=\"img_ev3q\"></p><div class=\"theme-admonition theme-admonition-tip alert alert--success admonition_LlT9\"><div class=\"admonitionHeading_tbUL\"><span class=\"admonitionIcon_kALy\"><svg viewBox=\"0 0 12 16\"><path fill-rule=\"evenodd\" d=\"M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z\"></path></svg></span>Update July 2023</div><div class=\"admonitionContent_S0QG\"><p>It is now also possible to retrigger the job, see\n<a href=\"/docs/retriggering\">the details</a>.</p></div></div><p>Also, if you need to do any change in the pull request, you need to locally fetch the source branch\nof the Packit's pull request and push it (with a fix) to your fork (as it is not possible to push to the branch\ncreated in the Packit's fork):</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">git fetch ssh://$USER.fedoraproject.org/forks/packit/rpms/$YOUR_PACKAGE.git refs/heads/*:refs/remotes/packit/*</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">git cherry-pick packit/$VERSION-$BRANCH-update-pull_from_upstream</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"few-words-in-the-end\">Few words in the end<a href=\"#few-words-in-the-end\" class=\"hash-link\" aria-label=\"Direct link to Few words in the end\" title=\"Direct link to Few words in the end\">​</a></h2><p><code>pull_from_upstream</code> has just been implemented; therefore, we encourage you to help\ntest it out and make it perfect! There are still some limitations (e.g. regarding upstreams,\nsee <a href=\"/docs/configuration/downstream/pull_from_upstream\">documentation</a>), which we are trying to resolve as soon as possible.\nWe believe this functionality\ncould be beneficial for maintainers of Fedora packages and could even be integrated further.\nAny <a href=\"https://github.com/packit/packit-service/issues/new\" target=\"_blank\" rel=\"noopener noreferrer\">suggestions</a> and feedback are welcomed\n(see <a href=\"/#contact\">contacts</a>).</p><p>If you are interested in details of customization of\nthe <code>pull_from_upstream</code> job and in the whole downstream automation, make sure to check out\n<a href=\"/docs/fedora-releases-guide\">our Fedora release guide</a> as well!</p>",
            "url": "https://packit.dev/posts/pull-from-upstream",
            "title": "Automatic pulling of upstream releases to Fedora",
            "summary": "In the previous year, we automated the Fedora downstream release process in Packit.",
            "date_modified": "2023-01-23T08:23:44.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "downstream"
            ]
        },
        {
            "id": "https://packit.dev/posts/testing-farm-triggering",
            "content_html": "<p>Do you contribute to projects which depend on each other?\nWould you like to test changes spanning multiple repositories together before merging them to the main branch?\nThen look no further, Packit's new feature of the Testing Farm integration is what you are looking for!</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"how-it-works\">How it works<a href=\"#how-it-works\" class=\"hash-link\" aria-label=\"Direct link to How it works\" title=\"Direct link to How it works\">​</a></h3><p>To enable such testing, there is no additional configuration required in your <code>packit.yaml</code>, the typical <a href=\"/docs/testing-farm\">Testing Farm configuration</a> is sufficient.\nOnce you open a pull request with some changes, tests are going to run as usual with all dependencies being installed based on the test definition, e.g. from Fedora repositories.\nTo trigger tests with builds from a pull request in another repository, add a comment to the pull request of the form:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">/packit test &lt;namespace&gt;/&lt;repo&gt;#&lt;pr-id&gt;</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>Based on this comment, Testing Farm will first install the recent successful builds created by Packit in the given pull request and then run the tests.\nIn order for this to work, there must be successful builds for the targets that you are running tests for.\nFor example, if you are testing against Fedora 36, the pull request that you want to install builds from must contain a successful Fedora 36 build by Packit.</p><p>Let's look at a simple example to demonstrate this feature better.\nThe Packit CLI uses a library called <code>specfile</code> to modify RPM spec files.\nRecently, <code>specfile</code> has added a new feature which makes accessing the <code>Epoch</code> field in the spec file more convenient and we would like to make use of this feature.\nHowever, the changes have not made it to a Fedora release yet, trying to use this feature will result in an error:</p><p><img loading=\"lazy\" alt=\"Tests in Testing Farm fail\" src=\"/assets/images/testing_farm_failed-f53ec0611bf89aee0e9eedd30a992814.png\" width=\"1091\" height=\"786\" class=\"img_ev3q\"></p><p><img loading=\"lazy\" alt=\"Test log in Testing Farm\" src=\"/assets/images/testing_farm_failed_log-b4f3f67d4ae5d36021eda7ef2f9d0030.png\" width=\"978\" height=\"353\" class=\"img_ev3q\"></p><p>As we can see in the screenshots, during artifact installation, the latest <code>specfile</code> release from Fedora was installed, however it lacks the feature that we are looking to test.\nLet's now retrigger the tests, but specify that we want to install builds from the pull request in <code>specfile</code> which introduced the changes:</p><p><img loading=\"lazy\" alt=\"Retriggering tests with builds from another PR\" src=\"/assets/images/testing_farm_retrigger-b67508e5263e2ee7f49b367670fcdd80.png\" width=\"1095\" height=\"727\" class=\"img_ev3q\"></p><p>Hooray! The copr builds from PR 165 were installed before the tests were run in Testing Farm which enabled us to test the feature inside Packit CLI.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"wrapping-up\">Wrapping up<a href=\"#wrapping-up\" class=\"hash-link\" aria-label=\"Direct link to Wrapping up\" title=\"Direct link to Wrapping up\">​</a></h3><p>We hope that this new feature makes upstream testing even more convenient than it previously was.\nThe feature is still quite new, and we would love to hear what you think about it.\nAs always, if you run into any trouble or have any ideas how to improve this functionality,\ndo not hesitate to <a href=\"/#contact\">reach out to us</a>.\nWe will be happy to help.</p>",
            "url": "https://packit.dev/posts/testing-farm-triggering",
            "title": "Running tests with builds from another PR",
            "summary": "Do you contribute to projects which depend on each other?",
            "date_modified": "2022-12-21T00:00:00.000Z",
            "author": {
                "name": "František Nečas",
                "url": "https://github.com/FrNecas"
            },
            "tags": [
                "testing-farm"
            ]
        },
        {
            "id": "https://packit.dev/posts/fas-verification-automation",
            "content_html": "<p>As you may already know, for using Packit Service\nGitHub App we <a href=\"/docs/guide#2-approval\">require our users to have a valid Fedora Account System account</a>.\nWe were verifying the newcomers until now manually, but in recent weeks, we have implemented an automated solution\nfor it. Let's take a closer look at how it is done currently and what have we improved!</p><p>Formerly, the process of verification by us started by waiting for the users to provide\nus their FAS username, then checking whether the provided FAS account\nexists and matches, and finally, manually adding the account to our allowlist in the database. For the communication with\nnew users, we have used our <a href=\"https://github.com/packit/notifications/issues\" target=\"_blank\" rel=\"noopener noreferrer\"><code>packit/notifications</code></a>\nrepository on GitHub where we created an issue for each new installation.</p><p>Although in general, this worked, it required human interaction and since we are not available 24/7, the verification wasn't immediate.\nWe wanted to simplify the process for both users and us.\nSince in FAS, everyone can set their GitHub login that is then publicly available, we decided to utilize this setting.</p><p>So how does the verification work now?</p><p>For each new GitHub installation, we first check whether there isn't a FAS account with the same login as the one\nthat triggered the installation. If we find such an account, we check whether the <code>GitHub Username</code> in this FAS account matches\nthe GitHub login of the one that triggered the installation. To get the information about the FAS accounts, we\nuse the <a href=\"https://github.com/fedora-infra/fasjson-client\" target=\"_blank\" rel=\"noopener noreferrer\"><code>fasjson-client</code> library</a>.\nIf this check doesn't prove any match, we create an issue in the\n<code>packit/notifications</code> repository as previously. This is what it looks like:</p><p><img loading=\"lazy\" alt=\"Issue in packit/notifications\" src=\"/assets/images/notifications-repo-issue-aca66e4b420cfe5d05c205fcf0020f92.png\" width=\"926\" height=\"467\" class=\"img_ev3q\"></p><p>As you can see, it contains instructions on how to trigger the verification automatically. So, everything the person who installed the app needs to do is set the <code>GitHub Username</code> field in their FAS account (if they don't have it set\nalready) and then provide the FAS login via Packit comment command <code>/packit verify-fas the-fas-account</code>.</p><p>Once the user does this, our service runs the same verification again (with the FAS username provided in the command) and informs users about the status\nvia a comment in the same issue. The successful verification looks like this:</p><p><img loading=\"lazy\" alt=\"Successful verification\" src=\"/assets/images/verify-fas-355a7111420aea52229c20f33a86322c.png\" width=\"932\" height=\"397\" class=\"img_ev3q\"></p><p>This should save both users and our time and hopefully make the onboarding process smoother for the newcomers.\nSince this is a pretty new feature,\nlet us know whether there is something that is not clear so that we can improve it.</p>",
            "url": "https://packit.dev/posts/fas-verification-automation",
            "title": "Automation of FAS verification in Packit Service",
            "summary": "As you may already know, for using Packit Service",
            "date_modified": "2022-05-24T00:00:00.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "fas"
            ]
        },
        {
            "id": "https://packit.dev/posts/downstream-automation",
            "content_html": "<p>Finally, it's here. Now, you can do the whole Fedora release with the help of Packit.\nLet's take a look at how it works on an example of <a href=\"https://github.com/packit/ogr\" target=\"_blank\" rel=\"noopener noreferrer\">OGR</a>, the Python library we develop.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"upstream\">Upstream<a href=\"#upstream\" class=\"hash-link\" aria-label=\"Direct link to Upstream\" title=\"Direct link to Upstream\">​</a></h2><p>The process of releasing a new version starts in the upstream repository.\nHere, we can see an upstream release:</p><p><img loading=\"lazy\" alt=\"Upstream release\" src=\"/assets/images/upstream_release-529c0916055286b228c4e1b631529fa4.png\" width=\"1108\" height=\"588\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"propose-downstream\">Propose downstream<a href=\"#propose-downstream\" class=\"hash-link\" aria-label=\"Direct link to Propose downstream\" title=\"Direct link to Propose downstream\">​</a></h2><p>As the first step on our way to Fedora users, we need to get the new upstream release to the Fedora dist-git.\nThis is what we call <code>propose-downstream</code> job.\nHere is a snippet from the config file of OGR:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token key atrule\" style=\"color:#00a4db\">downstream_package_name</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> python</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">ogr</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">copy_upstream_release_description</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">jobs</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> propose_downstream</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> release</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">dist_git_branches</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">all</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> epel</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token number\" style=\"color:#36acaa\">8</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>How does the <code>propose-downstream</code> work?\nAs a first step, the archive is saved to lookaside cache\nand after that, Packit updates the dist-git content (mainly <code>sources</code> file and spec-file)\nvia pull-requests for the specified branches. (Direct push is possible only for CLI by setting a\n<a href=\"https://packit.dev/docs/configuration/#create_pr\" target=\"_blank\" rel=\"noopener noreferrer\"><code>create_pr</code> option</a> to <code>false</code>.)</p><p>If you use <a href=\"https://packit.dev/docs/configuration/#copy_upstream_release_description\" target=\"_blank\" rel=\"noopener noreferrer\"><code>copy_upstream_release_description: true</code></a>,\nas in the config above,\nthe changelog entry will use the GitHub/GitLab release description field.\n(Just make sure the formatting is compatible with spec-file.\nE.g. use <code>-</code> instead of <code>*</code> for lists to not create multiple changelog entries.)</p><p>And how is it triggered?\nPackit gets the information about the newly created release from GitHub/GitLab (via webhook),\nloads the config from the release commit and if there is a <code>propose-downstream</code> job\ndefined, the workflow begins.</p><p>Here are the pull-requests created by Packit:</p><p><img loading=\"lazy\" alt=\"List of downstream pull-requests created by Packit\" src=\"/assets/images/distgit_prs-cf5788b3b23d52d771960621f308eab8.png\" width=\"1089\" height=\"420\" class=\"img_ev3q\"></p><p>And here are the details of the one created for <code>f35</code> branch:</p><p><img loading=\"lazy\" alt=\"Downstream pull-request created by Packit\" src=\"/assets/images/distgit_pr_detail-e34816e0dd354d7b35afc8131f517551.png\" width=\"736\" height=\"409\" class=\"img_ev3q\">\n<img loading=\"lazy\" alt=\"Downstream pull-request created by Packit: changes in specfile\" src=\"/assets/images/distgit_pr_specfile-134e1c00d39c6afb809ae31a5af19d66.png\" width=\"1094\" height=\"734\" class=\"img_ev3q\"></p><p>Now, it's on downstream CI systems and maintainer to check the changes and merge\nthe pull-request.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"koji\">Koji<a href=\"#koji\" class=\"hash-link\" aria-label=\"Direct link to Koji\" title=\"Direct link to Koji\">​</a></h2><p>If Packit sees a new commit in the configured dist-git branch, it submits a new build in Koji\nlike maintainers usually do. (The commits without any spec-file change are skipped.)</p><p><img loading=\"lazy\" alt=\"List of Koji builds triggered by Packit\" src=\"/assets/images/koji_builds-2f1af2ff0b81650da2cef9d25fcdaae4.png\" width=\"965\" height=\"141\" class=\"img_ev3q\"></p><p>Here is a job definition for the package we use as an example:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token key atrule\" style=\"color:#00a4db\">jobs</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> koji_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> commit</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">dist_git_branches</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">all</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> epel</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token number\" style=\"color:#36acaa\">8</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>There is no UI provided by Packit for the job,\nbut it is visible across Fedora systems (like you can see in the following image)\nlike a manually created Koji build and you can utilise\n<a href=\"https://apps.fedoraproject.org/notifications/about\" target=\"_blank\" rel=\"noopener noreferrer\">Fedora Notifications</a>\nto get informed about the builds.</p><p><img loading=\"lazy\" alt=\"Build status in merged downstream pull-request\" src=\"/assets/images/distgit_pr_build_status-3f4561f6c2fbdaaf76616bd060e80b23.png\" width=\"725\" height=\"499\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"bodhi\">Bodhi<a href=\"#bodhi\" class=\"hash-link\" aria-label=\"Direct link to Bodhi\" title=\"Direct link to Bodhi\">​</a></h2><p>Once Packit is informed (via fedora-messaging bus) about the successful Koji build,\nit creates a new update in Bodhi for you.</p><p><img loading=\"lazy\" alt=\"List of Bodhi updates created by Packit\" src=\"/assets/images/bodhi_updates-bb4320cda3965b1d3feff7b14e561373.png\" width=\"992\" height=\"222\" class=\"img_ev3q\"></p><p>Here is a job definition:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token key atrule\" style=\"color:#00a4db\">jobs</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token key atrule\" style=\"color:#00a4db\">job</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> bodhi_update</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">trigger</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> commit</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">dist_git_branches</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> fedora</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">branched </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># rawhide updates are created automatically</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> epel</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token number\" style=\"color:#36acaa\">8</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>The packit config is loaded from the commit the build is triggered from.</p><p>Here is an example of the resulting Bodhi update:</p><p><img loading=\"lazy\" alt=\"Bodhi update created by Packit\" src=\"/assets/images/bodhi_update_detail-c18320c042648314d31a9b4609aec94b.png\" width=\"743\" height=\"266\" class=\"img_ev3q\"></p><p>And that's all. The rest is on the users and maintainers to give the update enough Karma\nso the update gets to the users.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"conclusion\">Conclusion<a href=\"#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\">​</a></h2><p>Does it look simple? Yes, it is. We try to automate\nas much as possible but still leave the space for human intervention where it is needed --\npull-request review and verification of the Bodhi update.\nOf course, in case of some errors, a human can (and should)\nreplace the work of a bot.\nOther manual, mundane and waiting tasks are replaced by Packit.</p><p>Please, try it yourself and let us know what do you think.\nThose jobs are really new and some issues might occur.\nBut we will try to fix those and if you have any suggestions\nfor improvement, please, <a href=\"https://github.com/packit/packit-service/issues/new/choose\" target=\"_blank\" rel=\"noopener noreferrer\">create an issue</a> so we can\nsee if the request is doable and we can try to implement it.\nAnd of course, code contribution is more than welcome as well.</p>",
            "url": "https://packit.dev/posts/downstream-automation",
            "title": "Downstream automation is here",
            "summary": "Finally, it's here. Now, you can do the whole Fedora release with the help of Packit.",
            "date_modified": "2022-05-06T00:00:00.000Z",
            "author": {
                "name": "František Lachman",
                "url": "https://github.com/lachmanfrantisek"
            },
            "tags": [
                "propose-downstream"
            ]
        },
        {
            "id": "https://packit.dev/posts/copr-srpms",
            "content_html": "<p>Let's find out how Packit builds your SRPMs in the Copr.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"introduction\">Introduction<a href=\"#introduction\" class=\"hash-link\" aria-label=\"Direct link to Introduction\" title=\"Direct link to Introduction\">​</a></h3><p>If you use Packit to build RPMs for your upstream code changes, likely,\nyou have already read about how does Packit build your <a href=\"http://ftp.rpm.org/max-rpm/s1-rpm-miscellania-srpms.html\" target=\"_blank\" rel=\"noopener noreferrer\">SRPMs</a>.\nIf not, then just a short recap:\nEach time an RPM build is triggered, Packit builds an SRPM and then submits\nthe created SRPM file to Copr where Copr takes care of building the actual RPMs.\nSince you can modify the behaviour of building SRPMs by defining <a href=\"/docs/configuration/actions\">actions</a>,\nthis process needs to be run in an isolated environment. For this, we implemented our\n<a href=\"https://github.com/packit/sandcastle\" target=\"_blank\" rel=\"noopener noreferrer\">sandboxing mechanism</a>,\nwhich simply runs the provided commands in an Openshift pod freshly created for each build.</p><h4 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"problems-of-the-previous-workflow-for-srpm-builds\">Problems of the previous workflow for SRPM builds<a href=\"#problems-of-the-previous-workflow-for-srpm-builds\" class=\"hash-link\" aria-label=\"Direct link to Problems of the previous workflow for SRPM builds\" title=\"Direct link to Problems of the previous workflow for SRPM builds\">​</a></h4><p>This is a pretty good-functioning workflow, but it has some downsides which have become more and more annoying\nwith the growing user base. Because of the resources, we have set limits for Openshift pods running at one time.\nThis directly affects how many SRPM builds can run in parallel. As a result, when there are too many requests for (S)RPM builds,\nsome can get stuck in the queue while waiting for other builds to finish. Another inconvenience coming with pods being\nalways freshly created is copying the needed data into\nand from the pod. This has also cost us some months of desperate debugging of weird errors.\nAnother disadvantage is that users cannot easily configure dependencies for their actions run during building SRPMs.\nWe have to install the dependencies manually on-demand, but of course, which is not flexible.</p><p>We were thinking about improving the process for a long time but never reached any clear conclusion.\nThen in one of our architecture meetings, when we tried to solve another\nissue related to our sandboxing solution, Pavel Raiskup from Copr team asked us why didn't\nwe build the SRPMs directly in Copr. We knew that there is a way of building SRPMs in Copr,\nbut weren't aware of the details and how would this fit our use case.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"implementation-of-the-copr-srpms\">Implementation of the Copr SRPMs<a href=\"#implementation-of-the-copr-srpms\" class=\"hash-link\" aria-label=\"Direct link to Implementation of the Copr SRPMs\" title=\"Direct link to Implementation of the Copr SRPMs\">​</a></h3><p>After some research of the <a href=\"https://docs.pagure.org/copr.copr/custom_source_method.html\" target=\"_blank\" rel=\"noopener noreferrer\">Copr custom source method</a>, we\ndecided to give it a try. To make Copr build the SRPMs, Copr needs to be provided\nwith a script that will prepare the sources used to build an SRPM.\nTherefore, we created the <code>packit prepare-sources</code> command, which mostly reuses existing code that is run also in the sandbox\nworkflow. It prepares the specfile, archive and other sources and then moves\nthem to a separate directory. So with the new implementation,\nwith each request to run (S)RPM build, Packit sends a dynamically created \"script\" to Copr that invokes our new command.\nHere is what the script can look like:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">#!/bin/sh</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">git config --global user.email \"hello@packit.dev\"</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">git config --global user.name \"Packit\"</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">resultdir=$PWD</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">packit -d prepare-sources --result-dir \"$resultdir\" --pr-id 676 --job-config-index 2 https://github.com/packit/ogr</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>You can see that a pull request should be checked out or which job defined\nin your Packit job config is the trigger of this action. And that's it! Copr finds the sources and builds SRPM from them.\nPackit listens to the messages about the start and end of the build and similarily as for RPM builds, reports the\nstate via commit statuses/checks and provides the URL with the logs.</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"deployment-phases\">Deployment phases<a href=\"#deployment-phases\" class=\"hash-link\" aria-label=\"Direct link to Deployment phases\" title=\"Direct link to Deployment phases\">​</a></h3><p>Since this change is pretty significant, we wanted to start using this workflow gradually and catch all the problems\nbefore we get rid of the previous workflow for SRPMs.\nAt first, we tested how does the new solution work in our projects. The only disadvantage\nwas that the actual build process\ntakes a little longer than in sandcastle as we get an isolated environment where all the packages are installed for each new build.\nOn the other hand, Copr usually starts the build very soon after it is submitted, so no long wait time until some other build is finished.\nIn the initial implementation, we installed a list of dependencies\n<a href=\"https://github.com/packit/sandcastle/blob/ece539650770fea057877f0c97074acf506fada4/files/install-rpm-packages.yaml#L5\" target=\"_blank\" rel=\"noopener noreferrer\">which are present</a> in our\nsandbox which also increased the build time a bit.</p><p>So as the following step we added the functionality to define dependencies for actions in the\nPackit config file with <a href=\"/docs/configuration#srpm_build_deps\"><code>srpm_build_deps</code> key</a>.</p><p>Example of how the configuration of <code>srpm_build_deps</code> can look like:</p><div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token key atrule\" style=\"color:#00a4db\">actions</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">create-archive</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"python3 setup.py sdist --dist-dir .\"</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"sh -c 'echo packitos-$(python3 setup.py --version).tar.gz'\"</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">get-current-version</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"python3 setup.py --version\"</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">srpm_build_deps</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> python3</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">pip</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> python3</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">setuptools_scm</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>We also decided that presence of this key in the config will be for some period an indicator to build the SRPMs in Copr. With this approach, anyone can configure\ntheir dependencies and play with adding and adjusting them as needed without directly breaking\nthe builds in their repository. When the builds in the PR pass, the configuration change can be merged and the new approach\nwill be used for the whole repository. We wanted\nto kick off this process and therefore started opening PRs with dependencies configuration for projects that use\nthe RPM builds functionality the most. During this phase, you can reach out to us with your feedback, so we can\nimprove it even more!</p><p>As a next step, we use the new approach for GitHub app installations made since September 6, 2022.</p><p>And as of January 10th 2023, we switched to building all SRPMs in Copr\nand thus got rid of using our sandbox for building SRPMs entirely.</p><p>Since we don't want to break your CI results because of missing dependencies, we will use the previously linked list of deps.\nAs the list is pretty long, we encourage you to define your dependencies on your own. If you\nbump into any troubles with setting up SRPM builds in Copr, please,\n<a href=\"/#contact\">reach out to us</a>, we will be glad to help!</p>",
            "url": "https://packit.dev/posts/copr-srpms",
            "title": "Building SRPMs in Copr",
            "summary": "Let's find out how Packit builds your SRPMs in the Copr.",
            "date_modified": "2022-03-07T11:57:40.000Z",
            "author": {
                "name": "Laura Barcziová",
                "url": "https://github.com/lbarcziova"
            },
            "tags": [
                "srpm",
                "copr"
            ]
        },
        {
            "id": "https://packit.dev/posts/2021-features",
            "content_html": "<p>The previous year 2021 wasn't interesting only because of the increased usage of Packit\n(you can see more in <a href=\"/posts/2021-in-numbers\">the previous post</a>).\nThe whole Packit team made a lot of improvements during the year.\nSome small, some really big. So, let's take a look at the most important ones!</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"dashboard\">Dashboard<a href=\"#dashboard\" class=\"hash-link\" aria-label=\"Direct link to Dashboard\" title=\"Direct link to Dashboard\">​</a></h2><p>The idea of having a dashboard for Packit service started as a\n<a href=\"https://communityblog.fedoraproject.org/gsoc-progress-report-dashboard-for-packit-july-1-aug-16-2020/\" target=\"_blank\" rel=\"noopener noreferrer\">Google Summer of Code 2020 project</a>\nto provide a basic view of our service.\nThanks <a href=\"https://github.com/IceWreck\" target=\"_blank\" rel=\"noopener noreferrer\">Anchit</a> for starting this!\nNowadays, it's a core part of the project and it has replaced the result pages in plain HTML. Do you remember them?</p><p>The dashboard can be found at <a href=\"https://dashboard.packit.dev\" target=\"_blank\" rel=\"noopener noreferrer\">dashboard.packit.dev</a>.</p><p>Following picture shows a more convenient and visually-appealing view of builds and test runs.\nFor better context, the relevant pages are a connected to each other.</p><p><img loading=\"lazy\" alt=\"Dashboard: Copr Build result\" src=\"/assets/images/dashboard-copr-1a172fb72c00bb1b71af74610fc8ce7d.png\" width=\"1085\" height=\"776\" class=\"img_ev3q\"></p><p>If you want to see the overall picture, use our <a href=\"https://dashboard.packit.dev/pipelines\" target=\"_blank\" rel=\"noopener noreferrer\">pipelines view</a> that was created exactly for that:</p><p><img loading=\"lazy\" alt=\"Dashboard: Pipelines view\" src=\"/assets/images/dashboard-pipelines-03077187af2a61a8ab3a3fb1ed508d84.png\" width=\"1304\" height=\"721\" class=\"img_ev3q\"></p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"future-of-the-dashboard\">Future of the dashboard<a href=\"#future-of-the-dashboard\" class=\"hash-link\" aria-label=\"Direct link to Future of the dashboard\" title=\"Direct link to Future of the dashboard\">​</a></h3><p>We consider our dashboard an important part of our service and are working on or planning more improvements:</p><ul><li>We are working on personalised pages for a user or git-forge namespace.</li><li>We are planning to show info about other job types we support by the service as well;\nespecially the <code>propose-downstream</code> one.</li><li>We are doing some database schema updates to be able to better interconnect various pages.</li><li>Do you have an idea for an improvement?\nLet us know by creating an issue <a href=\"https://github.com/packit/dashboard/issues/new\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>.</li></ul><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"development\">Development<a href=\"#development\" class=\"hash-link\" aria-label=\"Direct link to Development\" title=\"Direct link to Development\">​</a></h2><p>From the very start, Packit is developed publicly in an open-source way.\nWe participate in various projects like Google Summer of Code, Red Hat Open Source Contest and Hacktoberfest.\nBut we are also very glad if anyone from our users contributes and fixes some pain point.\nTo help with that, we've renamed all our branches to <code>main</code> and rapidly enhanced our contribution guide(s).\nWe would like to encourage you not to be afraid of contributing to any of <a href=\"https://github.com/packit/\" target=\"_blank\" rel=\"noopener noreferrer\">our projects</a>.\nWe are prepared to help you with that.</p><p>If you want to keep an eye on what we are currently working on, check our <a href=\"https://github.com/orgs/packit/projects/4\" target=\"_blank\" rel=\"noopener noreferrer\"><em>Packit upstream work</em> board on GitHub</a>.</p><p><img loading=\"lazy\" alt=\"GitHub: Packit upstream work\" src=\"/assets/images/github-project-3606aa0b741a1835854a5cbfe59bcb15.png\" width=\"1298\" height=\"276\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"testing-farm\">Testing Farm<a href=\"#testing-farm\" class=\"hash-link\" aria-label=\"Direct link to Testing Farm\" title=\"Direct link to Testing Farm\">​</a></h2><p>The year 2021 was a tough one for our test workflow. For those who don't know, we use Testing Farm as our test runner.\nAt the beginning of the year, we switched to the new Testing Farm API version\n(because the old one had died with the infrastructure it had been running on).\nUnlike the old version, the new one fully supports <code>tmt</code> as a test definition.</p><p><img loading=\"lazy\" alt=\"Testing Farm: results\" src=\"/assets/images/testing-farm-results-976b2fa2b8055708c9bca93336fdad33.png\" width=\"1369\" height=\"436\" class=\"img_ev3q\"></p><p>During the year, a set of supported environments was enhanced by <code>centos-6</code>, <code>oraclelinux</code> and <code>aarch64</code>.\nFor Red Hat teams, we added support for using the internal instance of the Testing Farm.\nLet us know if you are interested in this.\nBut no worries, you can use <code>centos-stream</code> and other publicly available environments.</p><p>Originally, the tests were run after the installation of the packages built using Copr from the source repository.\nNewly, you can skip this step and run the tests without any build. This allows you to use Packit&amp;TestingFarm\nfor repositories containing only test definitions (e.g. QE teams).</p><p><img loading=\"lazy\" alt=\"Testing Farm: no build\" src=\"/assets/images/tf-no-build-9f7ecf53b820e6bfee6480256b97e69d.png\" width=\"1309\" height=\"194\" class=\"img_ev3q\"></p><p>Lastly, we send some environment variables to the test environment and you can define your own if you want.</p><p>As we see, testing is a key feature for some teams and we still want to improve test use-cases\n-- let us know if you are missing anything (<a href=\"https://github.com/packit/packit-service/issues/new\" target=\"_blank\" rel=\"noopener noreferrer\">here</a> or\n<a href=\"https://gitlab.com/groups/testing-farm/-/issues\" target=\"_blank\" rel=\"noopener noreferrer\">in the Testing Farm issue tracker</a>).</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"service\">Service<a href=\"#service\" class=\"hash-link\" aria-label=\"Direct link to Service\" title=\"Direct link to Service\">​</a></h2><p>To get users quickly know that we accepted the task and started working on it, we added two nice features\n-- <code>:1</code> reaction for the comment that we are reacting on and <code>task accepted</code> commit status.</p><p><img loading=\"lazy\" alt=\"Packit Service: reactions\" src=\"/assets/images/thumbs-up-5f8d2df5d24049a4154408995c65dad3.png\" width=\"950\" height=\"176\" class=\"img_ev3q\"></p><p>Speaking of statuses, we switched to a more feature-rich API called GitHub Check Runs.\nIt allows us to create a separate result page where we can show more information\n-- e.g. more links when needed and more space for hints when there is a problem.\nYou can also find the run results on a separate <code>Checks</code> tab of the pull-requests page.\nThe check run page contains only the basic info and we don't want to replace a dashboard with this.\n(Because of the consistency between git-forges and to be able to link the related dashboard pages.)\nAnother feature of check runs you might find useful is being able to re-run the failed test with just one click\n(see the <code>Re-run</code> button in the following screenshot).</p><p><img loading=\"lazy\" alt=\"Check runs\" src=\"/assets/images/check-runs-a38bf2a5d1febf4d3933a066dec2696c.png\" width=\"977\" height=\"384\" class=\"img_ev3q\"></p><p>Inspired by other systems (like Zuul), for pull-requests we started using merge state\nso you can be sure the state we use is the same as the one with the pull-request being merged.\nWe are working with the Testing Farm team to add the support there as well so the test definition is consistent with the build.\nBut no worries, you can disable this if you don't want this behaviour.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"downstream\">Downstream<a href=\"#downstream\" class=\"hash-link\" aria-label=\"Direct link to Downstream\" title=\"Direct link to Downstream\">​</a></h2><p>One of our current initiatives is to help maintainers in the downstream part of the workflow as well.\nWe had the first part of that for some time in a form of <code>propose-downstream</code> job (you can expect more enhancements on this front),\nbut we newly support triggering Koji builds for new commits in dist-git.</p><p>When there is a new dist-git commit that contains Packit config with the defined <code>koji_build</code> job,\nPackit will trigger the Koji build for you.\nIt's fresh and basic so far so give us some time to announce this with more details.\nThe next step will be to create a Bodhi update when the build successfully finishes and that is\nwhat is currently being worked on.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"status-page\">Status Page<a href=\"#status-page\" class=\"hash-link\" aria-label=\"Direct link to Status Page\" title=\"Direct link to Status Page\">​</a></h2><p>Yes, we have a status page where you can check if everything is ok with our service.\nIt can be found at <a href=\"https://status.packit.dev/\" target=\"_blank\" rel=\"noopener noreferrer\">status.packit.dev</a>\nOn the page, you can find a list of incidents we resolved or are trying to fix.\nIf you don't see any incident and still think the service isn't working as expected, please,\nlet us know (see <a href=\"/#contact\">contacts</a>).\nAnother useful source of information is the <a href=\"https://dashboard.packit.dev/pipelines\" target=\"_blank\" rel=\"noopener noreferrer\">pipelines view</a> on our dashboard.</p><p><img loading=\"lazy\" alt=\"Packit Status Page: systems\" src=\"/assets/images/status-1-161f9f8eab1e1c68007141a99dfda890.png\" width=\"575\" height=\"652\" class=\"img_ev3q\">\n<img loading=\"lazy\" alt=\"Packit Status Page: incidents\" src=\"/assets/images/status-2-870fd2bf13f962a7dc8e9ce1198436b5.png\" width=\"616\" height=\"697\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"future\">Future<a href=\"#future\" class=\"hash-link\" aria-label=\"Direct link to Future\" title=\"Direct link to Future\">​</a></h2><p>As you see, we managed to accomplish a lot last year. And what you can expect this year?\n<!-- -->[Let us know]<!-- -->({{&lt; ref \"faq#how-can-i-contact-you\" &gt;}}) if you have some ideas and want to influence that!</p>",
            "url": "https://packit.dev/posts/2021-features",
            "title": "2021 for Packit",
            "summary": "The previous year 2021 wasn't interesting only because of the increased usage of Packit",
            "date_modified": "2022-01-12T08:23:38.000Z",
            "author": {
                "name": "František Lachman",
                "url": "https://github.com/lachmanfrantisek"
            },
            "tags": [
                "2021",
                "yearly-features",
                "summary"
            ]
        },
        {
            "id": "https://packit.dev/posts/2021-in-numbers",
            "content_html": "<p>Let's take a look on the year 2021 through some numbers.\nWe would like to show you some interesting statistics and charts\nthat can describe the work of Packit during the year 2021.\nIf you are more interested in new features,\nlet's take a look on our <a href=\"/posts/2021-features\">second post</a>.</p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"github-application\">GitHub Application<a href=\"#github-application\" class=\"hash-link\" aria-label=\"Direct link to GitHub Application\" title=\"Direct link to GitHub Application\">​</a></h2><p>As of now, we have <code>169</code> installations of our GitHub application and <code>41</code> of them is from the year 2021.\nLooking at the monthly numbers below, it looks like we are getting back to shape.</p><p><img loading=\"lazy\" alt=\"GitHub installations in 2021\" src=\"/assets/images/github-installations-9dab680b453ba424a9fffa744270e432.png\" width=\"350\" height=\"210\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"builds\">Builds<a href=\"#builds\" class=\"hash-link\" aria-label=\"Direct link to Builds\" title=\"Direct link to Builds\">​</a></h2><p>Compared to the year 2020 when we made <code>28 430</code> Copr builds for our users,\nwe made <code>4.6</code> times more in the year 2021: <code>133 222</code> Copr builds.\nFor those who remember the start of our project,\nwe had a goal of <code>5</code> thousand for the <a href=\"https://flocktofedora.org/\" target=\"_blank\" rel=\"noopener noreferrer\">FLOCK</a> 2019.\nWe are now two digits ahead!\nAnd if you are wondering how active is our user on Copr,\nwe've created <code>2/3</code> of all the new Copr projects during the year.</p><p>To made this happen, we've created <code>36 133</code> source RPM files in the year 2021.</p><p><img loading=\"lazy\" alt=\"Copr builds in 2021\" src=\"/assets/images/copr-builds-dd34dfb527eb67affe3ddfad09436f25.png\" width=\"362\" height=\"211\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"test-runs\">Test runs<a href=\"#test-runs\" class=\"hash-link\" aria-label=\"Direct link to Test runs\" title=\"Direct link to Test runs\">​</a></h2><p>Sadly, we started saving the submit time of the test runs in June\nso we have numbers only for the second half of the year.\nThe numbers are not so high as for the builds but still <code>18 498</code> test runs.</p><p><img loading=\"lazy\" alt=\"Test runs in 2021\" src=\"/assets/images/test-runs-e97a55c365a585076c678f29f29b3fd4.png\" width=\"364\" height=\"211\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"top-20-projects-in-the-number-of-pr-copr-builds\">Top 20 projects in the number of PR Copr Builds<a href=\"#top-20-projects-in-the-number-of-pr-copr-builds\" class=\"hash-link\" aria-label=\"Direct link to Top 20 projects in the number of PR Copr Builds\" title=\"Direct link to Top 20 projects in the number of PR Copr Builds\">​</a></h2><p><img loading=\"lazy\" alt=\"Top20 projects in the number of PR Copr Builds\" src=\"/assets/images/top20-copr-builds-02b2a99641f6d7005a189512c9b1f7a0.png\" width=\"639\" height=\"377\" class=\"img_ev3q\"></p><h2 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"top-20-projects-in-the-number-of-pr-test-runs\">Top 20 projects in the number of PR test runs<a href=\"#top-20-projects-in-the-number-of-pr-test-runs\" class=\"hash-link\" aria-label=\"Direct link to Top 20 projects in the number of PR test runs\" title=\"Direct link to Top 20 projects in the number of PR test runs\">​</a></h2><p><img loading=\"lazy\" alt=\"Top20 projects in the number of PR Test runs\" src=\"/assets/images/top20-test-runs-a6d4a360be98fb3f66fb65f0d5a46be0.png\" width=\"640\" height=\"377\" class=\"img_ev3q\"></p>",
            "url": "https://packit.dev/posts/2021-in-numbers",
            "title": "2021 in Numbers",
            "summary": "Let's take a look on the year 2021 through some numbers.",
            "date_modified": "2022-01-04T00:00:00.000Z",
            "author": {
                "name": "František Lachman",
                "url": "https://github.com/lachmanfrantisek"
            },
            "tags": [
                "2021",
                "yearly-numbers",
                "summary"
            ]
        },
        {
            "id": "https://packit.dev/posts/fedora-eln",
            "content_html": "<p><a href=\"https://docs.fedoraproject.org/en-US/eln/\" target=\"_blank\" rel=\"noopener noreferrer\">Fedora EL Niño</a> (ELN) is such an\nawesome idea. It enables building rawhide packages in two distinct buildroots:</p><ol><li>the standard Fedora Rawhide buildroot and</li><li>a second one, which mimics Red Hat Enterprise Linux</li></ol><p>This way you can make sure that your new upstream release builds fine in the\nnext RHEL.</p><p>But this feedback might be a little bit too late: the upstream\nrelease already happened and the code was imported in Fedora dist-git, so\nfixing an issue will require repeating the whole process. Wouldn't it be better\nto know if the upstream change builds fine in ELN <strong>while</strong> working on the\ncode?</p><p>Oh, wait!</p><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"you-can-do-this-easily-with-packit\">You can do this easily with Packit<a href=\"#you-can-do-this-easily-with-packit\" class=\"hash-link\" aria-label=\"Direct link to You can do this easily with Packit\" title=\"Direct link to You can do this easily with Packit\">​</a></h3><p>If your GitHub project is not using Packit yet, <a href=\"https://packit.dev/docs/guide\" target=\"_blank\" rel=\"noopener noreferrer\">here's a\nguide</a> how to start.</p><p>Once it's set up, you need to make sure that your pull requests are also being\nbuilt in the <code>fedora-eln</code> target:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">jobs:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  - job: copr_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    trigger: pull_request</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    metadata:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      targets:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        - fedora-development</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        - fedora-eln</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>With this config, changes from every pull request will be built in all\ndevelopment versions of Fedora (at the time of writing this, it's Rawhide and\nFedora 33) and in Fedora ELN.</p><p>Easy, right?</p><p>Packit can also trigger builds when you push to a branch. If you want to have\nup to date builds of your main branch for ELN and development versions of\nFedora, here's how to set it up:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">jobs:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  - job: copr_build</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    trigger: commit</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    metadata:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      targets:</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        - fedora-development</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        - fedora-eln</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      branch: main</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><h3 class=\"anchor anchorWithStickyNavbar_LWe7\" id=\"a-real-life-example\">A real-life example<a href=\"#a-real-life-example\" class=\"hash-link\" aria-label=\"Direct link to A real-life example\" title=\"Direct link to A real-life example\">​</a></h3><p>If you got here and you're still not sure why you'd need this, I can give\nyou a real-life example.</p><p>Recently, <a href=\"https://github.com/jkonecny12\" target=\"_blank\" rel=\"noopener noreferrer\">Jirka Konecny</a> from the RHEL\nInstaller team reached out to us that they would love to use Packit as a CI\nsystem. He set it up and now all the anaconda PRs are being built and tested on\n<code>Fedora Rawhide x86_64</code>.</p><p><img loading=\"lazy\" alt=\"Anaconda PR passing tests\" src=\"/assets/images/anaconda-rawhide-tests-passing-4fd8c7a3455a72981b0fe9509fdd48fb.png\" width=\"1205\" height=\"725\" class=\"img_ev3q\"></p><p>Jirka continued and added Fedora ELN as an additional target. The build failed\nbecause one of build requirements was not available in ELN:</p><div class=\"codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_biex\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\"><code class=\"codeBlockLines_e6Vv\"><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Fedora ELN - Developmental modular packages for the next Enterprise Linux release               2.7 kB/s | 2.3 kB     00:0</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">No matching package to install: 'metacity'</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Not all dependencies satisfied</span><br></span><span class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Error: Some packages could not be found.</span><br></span></code></pre><div class=\"buttonGroup__atx\"><button type=\"button\" aria-label=\"Copy code to clipboard\" title=\"Copy\" class=\"clean-btn\"><span class=\"copyButtonIcons_eSgA\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" class=\"copyButtonIcon_y97N\"><path fill=\"currentColor\" d=\"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"></path></svg><svg viewBox=\"0 0 24 24\" class=\"copyButtonSuccessIcon_LjdS\"><path fill=\"currentColor\" d=\"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z\"></path></svg></span></button></div></div></div><p>Since the team discovered this during their upstream development process, they\ncan react to the issue right away. It would have been pretty late if they found this\nwhile the next major RHEL is reaching alpha - at this moment they should\nhave enough time to fix the problem and make sure anaconda builds fine in ELN.</p><p>So, are you convinced? Let us know if you need help setting up Packit in your\nupstream repositories :)</p>",
            "url": "https://packit.dev/posts/fedora-eln",
            "title": "Working on the next major RHEL release, in your upstream repo",
            "summary": "Fedora EL Niño (ELN) is such an",
            "date_modified": "2020-10-04T00:00:00.000Z",
            "author": {
                "name": "Tomáš Tomeček",
                "url": "https://github.com/TomasTomecek"
            },
            "tags": [
                "downstream"
            ]
        }
    ]
}