From db68323e541e79ed31fa5c737425ca7057192758 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Fri, 11 Jul 2025 12:25:47 +0200 Subject: [PATCH] feat: `init --gihub` to create README and test/publish workflows (#1972) * Templates for Github and `init --github` * Builtin to permanently enable --github * Unit test for To_Boolean * Test for user behavior * Document user-visible changes * Test tweaks for explicit builtin use * Attempt at guessing the PR number * Better builtin fix * Self-review * Fabien's review * Regenerate templates * Don't show diffs for "binary" generated templates --- .gitattributes | 3 + doc/user-changes.md | 9 ++ src/alire/alire-settings-builtins.ads | 9 ++ src/alire/alire-settings-edit.adb | 26 +++--- src/alire/alire-settings.adb | 7 +- src/alire/alire-settings.ads | 1 + src/alire/alire-templates-builtins.ads | 10 ++ src/alr/alr-commands-init.adb | 36 ++++++++ src/alr/alr-commands-init.ads | 1 + src/alr/alr-commands.adb | 4 +- src/alr/alr-commands.ads | 5 +- src/templates/r-github_publish_yml.ads | 86 ++++++++++++++++++ src/templates/r-github_readme_md.ads | 32 +++++++ src/templates/r-github_selftest_yml.ads | 84 +++++++++++++++++ src/templates/r.adb | 91 +++++++++++-------- support/embedder/templates.hash | 2 +- templates/github/README.md | 7 ++ templates/github/publish.yml | 28 ++++++ templates/github/selftest.yml | 34 +++++++ testsuite/drivers/alr.py | 17 +++- .../tests/get/custom-download-command/test.py | 5 +- testsuite/tests/init/github-files/test.py | 56 ++++++++++++ testsuite/tests/init/github-files/test.yaml | 1 + testsuite/tests/workflows/air-gapping/test.py | 11 ++- .../src/alr_tests-commands_to_boolean.adb | 64 +++++++++++++ .../src_common/alr-commands-testing.adb | 12 +++ .../src_common/alr-commands-testing.ads | 11 +++ 27 files changed, 583 insertions(+), 69 deletions(-) create mode 100644 src/templates/r-github_publish_yml.ads create mode 100644 src/templates/r-github_readme_md.ads create mode 100644 src/templates/r-github_selftest_yml.ads create mode 100644 templates/github/README.md create mode 100644 templates/github/publish.yml create mode 100644 templates/github/selftest.yml create mode 100644 testsuite/tests/init/github-files/test.py create mode 100644 testsuite/tests/init/github-files/test.yaml create mode 100644 testsuite/tests_ada/src/alr_tests-commands_to_boolean.adb create mode 100644 testsuite/tests_ada/src_common/alr-commands-testing.adb create mode 100644 testsuite/tests_ada/src_common/alr-commands-testing.ads diff --git a/.gitattributes b/.gitattributes index 86ec7aad..eeca2124 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,3 +11,6 @@ *.pdf -text *.png -text *.tgz -text + +# Mark templates as generated so their diff is hidden by default at GitHub +src/templates/** linguist-generated=true diff --git a/doc/user-changes.md b/doc/user-changes.md index 6544d995..1a503c70 100644 --- a/doc/user-changes.md +++ b/doc/user-changes.md @@ -6,6 +6,15 @@ stay on top of `alr` new features. ## Release `3.0` +### New `--github` switch for `alr init` command + +PR [#1972](https://github.com/alire-project/alire/pull/1972) + +The `alr init` command now supports a `--github` switch to automatically +generate GitHub files (README.md, workflows) for new crates. This can be +controlled with `--github[=true/false]` or by setting the new built-in +`init.github_files` setting. + ### Style checks disabled by default in all build profiles PR [#1919](https://github.com/alire-project/alire/pull/1919) diff --git a/src/alire/alire-settings-builtins.ads b/src/alire/alire-settings-builtins.ads index c6bc7b5e..904c76da 100644 --- a/src/alire/alire-settings-builtins.ads +++ b/src/alire/alire-settings-builtins.ads @@ -113,6 +113,15 @@ package Alire.Settings.Builtins is Def => "alire-index", Help => "Name of the index repository."); + -- INIT + + Init_Github_Files : constant Builtin := New_Builtin + (Key => "init.github_files", + Def => False, + Help => + "When True, a README and workflows for GitHub will be created by " + & "default during `alr init` (equivalent to `alr init --github`)"); + -- ORIGINS Origins_Archive_Download_Cmd : constant Builtin := New_Builtin diff --git a/src/alire/alire-settings-edit.adb b/src/alire/alire-settings-edit.adb index 02bf7c11..912b2ea9 100644 --- a/src/alire/alire-settings-edit.adb +++ b/src/alire/alire-settings-edit.adb @@ -379,12 +379,14 @@ package body Alire.Settings.Edit is Results : AAA.Strings.Vector; begin for Ent of All_Builtins loop - Results.Append (String'("- " & TTY.Bold (To_String (Ent.Key)) - & " [" & TTY.Emph (Image (Ent.Kind)) & "]" - & "[Default:" & TTY.Terminal (To_String (Ent.Def)) - & "]")); - Results.Append (To_String (Ent.Help)); - Results.Append (""); + if Ent.Public then + Results.Append (String'("- " & TTY.Bold (To_String (Ent.Key)) + & " [" & TTY.Emph (Image (Ent.Kind)) & "]" + & "[Default:" & TTY.Terminal (To_String (Ent.Def)) + & "]")); + Results.Append (To_String (Ent.Help)); + Results.Append (""); + end if; end loop; return Results; end Builtins_Info; @@ -397,11 +399,13 @@ package body Alire.Settings.Edit is use Ada.Text_IO; begin for Ent of All_Builtins loop - Put (" - **`" & To_String (Ent.Key) & "`** "); - Put ("[" & Image (Ent.Kind) & "]"); - Put_Line ("[Default:" & To_String (Ent.Def) & "]:"); - Put_Line (" " & To_String (Ent.Help)); - New_Line; + if Ent.Public then + Put (" - **`" & To_String (Ent.Key) & "`** "); + Put ("[" & Image (Ent.Kind) & "]"); + Put_Line ("[Default:" & To_String (Ent.Def) & "]:"); + Put_Line (" " & To_String (Ent.Help)); + New_Line; + end if; end loop; end Print_Builtins_Doc; diff --git a/src/alire/alire-settings.adb b/src/alire/alire-settings.adb index 635c94aa..25450605 100644 --- a/src/alire/alire-settings.adb +++ b/src/alire/alire-settings.adb @@ -159,11 +159,10 @@ package body Alire.Settings is Def => +Def, Help => +Help, Global_Only => Global_Only, - Check => Check) + Check => Check, + Public => Public) do - if Public then - All_Builtins.Insert (Key, Result); - end if; + All_Builtins.Insert (Key, Result); end return; end New_Builtin; diff --git a/src/alire/alire-settings.ads b/src/alire/alire-settings.ads index 7f4bead3..c6afcdf2 100644 --- a/src/alire/alire-settings.ads +++ b/src/alire/alire-settings.ads @@ -98,6 +98,7 @@ private Help : Ada.Strings.Unbounded.Unbounded_String; Check : CLIC.Config.Check_Import := null; Global_Only : Boolean := False; + Public : Boolean := True; end record; -------------- diff --git a/src/alire/alire-templates-builtins.ads b/src/alire/alire-templates-builtins.ads index 87d92087..e87f74f7 100644 --- a/src/alire/alire-templates-builtins.ads +++ b/src/alire/alire-templates-builtins.ads @@ -16,6 +16,10 @@ with R.Crate_Test_Tests_Common_Name_Tests_Ads; with R.Crate_Test_Tests_Crate_Test_Tests_Gpr; with R.Crate_Test_Tests_Src_Name_Testsxassertions_Enabled_Adb; +with R.Github_Publish_Yml; +with R.Github_Readme_Md; +with R.Github_Selftest_Yml; + private with Alire.TOML_Adapters; package Alire.Templates.Builtins is @@ -80,6 +84,12 @@ package Alire.Templates.Builtins is .Append ("src/@_NAME_@_tests-assertions_enabled.adb", +R.Crate_Test_Tests_Src_Name_Testsxassertions_Enabled_Adb.Content) ; + Github : constant Tree := New_Tree + .Append (".github/workflows/publish.yml", +R.Github_Publish_Yml.Content) + .Append (".github/workflows/selftest.yml", +R.Github_Selftest_Yml.Content) + .Append ("README.md", +R.Github_Readme_Md.Content) + ; + private pragma Style_Checks (On); diff --git a/src/alr/alr-commands-init.adb b/src/alr/alr-commands-init.adb index 298dbf90..1033ab4b 100644 --- a/src/alr/alr-commands-init.adb +++ b/src/alr/alr-commands-init.adb @@ -26,6 +26,8 @@ package body Alr.Commands.Init is type Crate_Kind is (Library, Binary); + Switch_Github : constant String := "--github"; + -------------- -- Generate -- -------------- @@ -101,6 +103,18 @@ package body Alr.Commands.Init is end if; end Generate_Test_Crate; + --------------------------- + -- Generate_Github_Files -- + --------------------------- + + procedure Generate_Github_Files is + begin + Templates.Translate_Tree + (Directory, + Templates.Builtins.Github, + Templates.Builtins.Init_Crate_Translation (Info)); + end Generate_Github_Files; + begin if Cmd.No_Skel then @@ -117,6 +131,13 @@ package body Alr.Commands.Init is end if; end if; + if To_Boolean (Image => Cmd.Github, + Switch => Switch_Github, + Default => Alire.Settings.Builtins.Init_Github_Files.Get) + then + Generate_Github_Files; + end if; + Alire.Put_Success (TTY.Emph (Name.As_String) & " initialized successfully."); end Generate; @@ -372,6 +393,8 @@ package body Alr.Commands.Init is Builtins.User_Email.Is_Empty or else Builtins.User_Name.Is_Empty or else Builtins.User_Github_Login.Is_Empty; + + Unused : Boolean; begin Cmd.Forbids_Structured_Output; @@ -379,6 +402,11 @@ package body Alr.Commands.Init is Reportaise_Wrong_Arguments ("Please provide either --bin or --lib"); end if; + -- Validate --github (To_Boolean does the checks) + Unused := To_Boolean (Image => Cmd.Github, + Switch => Switch_Github, + Default => False); + Info.With_Test := not (Cmd.No_Test or else Cmd.No_Skel); Query_Crate_Name (Args, Info); @@ -428,6 +456,7 @@ package body Alr.Commands.Init is " for the crate:", Default => "", Validation => null)); + Generate (Cmd, Info); end Execute; @@ -483,6 +512,13 @@ package body Alr.Commands.Init is "", "--no-test", "Do not generate a minimal test crate skeleton" & " (implied by --no-skel)"); + + Define_Switch (Config, + Cmd.Github'Access, + "", Switch_Github & "?", + Argument => "=BOOL", + Help => + "Generate README and workflows for GitHub projects"); end Setup_Switches; end Alr.Commands.Init; diff --git a/src/alr/alr-commands-init.ads b/src/alr/alr-commands-init.ads index 42e9cafb..48faad06 100644 --- a/src/alr/alr-commands-init.ads +++ b/src/alr/alr-commands-init.ads @@ -37,6 +37,7 @@ private In_Place, No_Skel, No_Test : aliased Boolean := False; + Github : aliased GNAT_String := new String'(Unset); end record; end Alr.Commands.Init; diff --git a/src/alr/alr-commands.adb b/src/alr/alr-commands.adb index 1c416e81..9dc22bb9 100644 --- a/src/alr/alr-commands.adb +++ b/src/alr/alr-commands.adb @@ -740,8 +740,10 @@ package body Alr.Commands is return Boolean is begin - if Image in null or else Image.all = "" or else Image.all = Unset then + if Image in null or else Image.all = Unset then return Default; + elsif Image.all = "" or else Image.all = "=" then + return True; elsif Is_Boolean (Image.all) then return Boolean'Value (Image.all); elsif Image (Image'First) = '=' then diff --git a/src/alr/alr-commands.ads b/src/alr/alr-commands.ads index 6cad7c0a..7d2fee70 100644 --- a/src/alr/alr-commands.ads +++ b/src/alr/alr-commands.ads @@ -171,10 +171,11 @@ private Default : Boolean) return Boolean with Post => - (if Image in null or else Image.all = "" or else Image.all = Unset + (if Image in null or else Image.all = Unset then To_Boolean'Result = Default); -- Convert a switch value to a boolean, if explicitly given, or use the -- default otherwise. If not a valid boolean or empty, raise Checked_Error - -- with an appropriate error message. + -- with an appropriate error message. NOTE: If the switch exists (is not + -- unset) but has no argument, it's considered TRUE, not default. end Alr.Commands; diff --git a/src/templates/r-github_publish_yml.ads b/src/templates/r-github_publish_yml.ads new file mode 100644 index 00000000..5ca09cad --- /dev/null +++ b/src/templates/r-github_publish_yml.ads @@ -0,0 +1,86 @@ + +-- Generated by awsres from /support/embedder/embedder.sh + +pragma Style_Checks (Off); + +with Ada.Streams; + +package r.github_publish_yml is + + use Ada.Streams; + + Content : aliased constant Stream_Element_Array := + (110, 97, 109, 101, 58, 32, 80, 117, 98, 108, 105, 115, 104, 10, + 10, 35, 32, 82, 69, 81, 85, 73, 82, 69, 83, 32, 97, 32, + 115, 101, 99, 114, 101, 116, 32, 110, 97, 109, 101, 100, 32, 65, + 76, 82, 95, 80, 85, 66, 76, 73, 83, 72, 95, 80, 65, 84, + 32, 116, 111, 32, 98, 101, 32, 115, 101, 116, 32, 105, 110, 32, + 116, 104, 101, 32, 114, 101, 112, 111, 115, 105, 116, 111, 114, 121, + 10, 35, 32, 99, 111, 110, 116, 97, 105, 110, 105, 110, 103, 32, + 97, 32, 116, 111, 107, 101, 110, 32, 119, 105, 116, 104, 32, 119, + 114, 105, 116, 101, 32, 97, 99, 99, 101, 115, 115, 32, 116, 111, + 32, 116, 104, 101, 32, 114, 101, 112, 111, 115, 105, 116, 111, 114, + 121, 32, 40, 102, 111, 114, 32, 116, 97, 103, 103, 105, 110, 103, + 32, 97, 110, 100, 10, 35, 32, 114, 101, 108, 101, 97, 115, 105, + 110, 103, 41, 32, 97, 110, 100, 32, 102, 111, 114, 107, 105, 110, + 103, 32, 112, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 32, + 40, 116, 111, 32, 99, 114, 101, 97, 116, 101, 32, 97, 32, 102, + 111, 114, 107, 32, 111, 102, 32, 116, 104, 101, 32, 99, 111, 109, + 109, 117, 110, 105, 116, 121, 32, 105, 110, 100, 101, 120, 10, 35, + 32, 97, 110, 100, 32, 99, 111, 109, 109, 105, 116, 32, 99, 104, + 97, 110, 103, 101, 115, 32, 116, 111, 32, 105, 116, 41, 46, 10, + 10, 35, 32, 82, 117, 110, 110, 105, 110, 103, 32, 116, 104, 105, + 115, 32, 119, 111, 114, 107, 102, 108, 111, 119, 32, 119, 105, 108, + 108, 32, 111, 112, 101, 110, 32, 97, 32, 80, 82, 32, 97, 103, + 97, 105, 110, 115, 116, 32, 116, 104, 101, 32, 99, 111, 109, 109, + 117, 110, 105, 116, 121, 32, 105, 110, 100, 101, 120, 32, 102, 111, + 114, 32, 116, 104, 101, 10, 35, 32, 118, 101, 114, 115, 105, 111, + 110, 32, 97, 116, 32, 116, 104, 101, 32, 99, 117, 114, 114, 101, + 110, 116, 32, 99, 111, 109, 109, 105, 116, 46, 32, 66, 121, 32, + 100, 101, 102, 97, 117, 108, 116, 44, 32, 105, 116, 32, 97, 108, + 115, 111, 32, 119, 105, 108, 108, 32, 99, 114, 101, 97, 116, 101, + 32, 97, 32, 116, 97, 103, 32, 97, 110, 100, 10, 35, 32, 114, + 101, 108, 101, 97, 115, 101, 46, 32, 72, 101, 110, 99, 101, 44, + 32, 105, 116, 32, 105, 115, 32, 114, 101, 99, 111, 109, 109, 101, + 110, 100, 101, 100, 32, 116, 111, 32, 111, 110, 108, 121, 32, 116, + 114, 105, 103, 103, 101, 114, 32, 105, 116, 32, 119, 104, 101, 110, + 32, 111, 110, 101, 32, 105, 115, 32, 99, 101, 114, 116, 97, 105, + 110, 32, 97, 108, 108, 10, 35, 32, 116, 101, 115, 116, 115, 32, + 104, 97, 118, 101, 32, 115, 117, 99, 99, 101, 101, 100, 101, 100, + 32, 102, 111, 114, 32, 116, 104, 101, 32, 118, 101, 114, 115, 105, + 111, 110, 32, 98, 101, 105, 110, 103, 32, 115, 117, 98, 109, 105, + 116, 116, 101, 100, 46, 10, 10, 111, 110, 58, 10, 32, 32, 119, + 111, 114, 107, 102, 108, 111, 119, 95, 100, 105, 115, 112, 97, 116, + 99, 104, 58, 32, 35, 32, 69, 110, 97, 98, 108, 101, 115, 32, + 109, 97, 110, 117, 97, 108, 32, 116, 114, 105, 103, 103, 101, 114, + 105, 110, 103, 32, 111, 102, 32, 116, 104, 101, 32, 119, 111, 114, + 107, 102, 108, 111, 119, 10, 10, 106, 111, 98, 115, 58, 10, 32, + 32, 112, 117, 98, 108, 105, 115, 104, 58, 10, 32, 32, 32, 32, + 114, 117, 110, 115, 45, 111, 110, 58, 32, 117, 98, 117, 110, 116, + 117, 45, 108, 97, 116, 101, 115, 116, 10, 32, 32, 32, 32, 115, + 116, 101, 112, 115, 58, 10, 32, 32, 32, 32, 32, 32, 45, 32, + 117, 115, 101, 115, 58, 32, 97, 108, 105, 114, 101, 45, 112, 114, + 111, 106, 101, 99, 116, 47, 97, 108, 114, 45, 112, 117, 98, 108, + 105, 115, 104, 64, 118, 49, 10, 32, 32, 32, 32, 32, 32, 32, + 32, 119, 105, 116, 104, 58, 10, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 103, 105, 116, 104, 117, 98, 95, 116, 111, 107, 101, + 110, 58, 32, 36, 123, 123, 32, 115, 101, 99, 114, 101, 116, 115, + 46, 65, 76, 82, 95, 80, 85, 66, 76, 73, 83, 72, 95, 80, + 65, 84, 32, 125, 125, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 115, 107, 105, 112, 95, 98, 117, 105, 108, 100, 58, 32, + 102, 97, 108, 115, 101, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 99, 114, 101, 97, 116, 101, 95, 116, 97, 103, 58, 32, + 116, 114, 117, 101, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 99, 114, 101, 97, 116, 101, 95, 114, 101, 108, 101, 97, 115, + 101, 58, 32, 116, 114, 117, 101, 10, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 35, 32, 67, 104, 101, 99, 107, 10, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 35, 32, 104, 116, 116, 112, + 115, 58, 47, 47, 103, 105, 116, 104, 117, 98, 46, 99, 111, 109, + 47, 97, 108, 105, 114, 101, 45, 112, 114, 111, 106, 101, 99, 116, + 47, 97, 108, 114, 45, 112, 117, 98, 108, 105, 115, 104, 47, 98, + 108, 111, 98, 47, 108, 97, 116, 101, 115, 116, 47, 97, 99, 116, + 105, 111, 110, 46, 121, 109, 108, 10, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 35, 32, 102, 111, 114, 32, 109, 111, 114, 101, + 32, 111, 112, 116, 105, 111, 110, 115, 46, 10); + +end r.github_publish_yml; diff --git a/src/templates/r-github_readme_md.ads b/src/templates/r-github_readme_md.ads new file mode 100644 index 00000000..13ad6101 --- /dev/null +++ b/src/templates/r-github_readme_md.ads @@ -0,0 +1,32 @@ + +-- Generated by awsres from /support/embedder/embedder.sh + +pragma Style_Checks (Off); + +with Ada.Streams; + +package r.github_readme_md is + + use Ada.Streams; + + Content : aliased constant Stream_Element_Array := + (60, 33, 45, 45, 32, 85, 110, 99, 111, 109, 109, 101, 110, 116, + 32, 116, 111, 32, 103, 101, 116, 32, 97, 32, 98, 97, 100, 103, + 101, 32, 111, 110, 99, 101, 32, 116, 104, 101, 32, 99, 114, 97, + 116, 101, 32, 105, 115, 32, 112, 117, 98, 108, 105, 115, 104, 101, + 100, 46, 10, 91, 33, 91, 65, 108, 105, 114, 101, 93, 40, 104, + 116, 116, 112, 115, 58, 47, 47, 105, 109, 103, 46, 115, 104, 105, + 101, 108, 100, 115, 46, 105, 111, 47, 101, 110, 100, 112, 111, 105, + 110, 116, 63, 117, 114, 108, 61, 104, 116, 116, 112, 115, 58, 47, + 47, 97, 108, 105, 114, 101, 46, 97, 100, 97, 46, 100, 101, 118, + 47, 98, 97, 100, 103, 101, 115, 47, 64, 95, 76, 79, 87, 69, + 82, 58, 78, 65, 77, 69, 95, 64, 46, 106, 115, 111, 110, 41, + 93, 40, 104, 116, 116, 112, 115, 58, 47, 47, 97, 108, 105, 114, + 101, 46, 97, 100, 97, 46, 100, 101, 118, 47, 99, 114, 97, 116, + 101, 115, 47, 64, 95, 76, 79, 87, 69, 82, 58, 78, 65, 77, + 69, 95, 64, 46, 104, 116, 109, 108, 41, 10, 45, 45, 62, 10, + 10, 35, 32, 64, 95, 85, 80, 80, 69, 82, 58, 78, 65, 77, + 69, 95, 64, 10, 10, 64, 95, 68, 69, 83, 67, 82, 73, 80, + 84, 73, 79, 78, 95, 64); + +end r.github_readme_md; diff --git a/src/templates/r-github_selftest_yml.ads b/src/templates/r-github_selftest_yml.ads new file mode 100644 index 00000000..6f3261f6 --- /dev/null +++ b/src/templates/r-github_selftest_yml.ads @@ -0,0 +1,84 @@ + +-- Generated by awsres from /support/embedder/embedder.sh + +pragma Style_Checks (Off); + +with Ada.Streams; + +package r.github_selftest_yml is + + use Ada.Streams; + + Content : aliased constant Stream_Element_Array := + (110, 97, 109, 101, 58, 32, 84, 101, 115, 116, 10, 10, 111, 110, + 58, 10, 32, 32, 112, 117, 115, 104, 58, 10, 32, 32, 32, 32, + 98, 114, 97, 110, 99, 104, 101, 115, 58, 10, 32, 32, 32, 32, + 32, 32, 45, 32, 109, 97, 105, 110, 10, 32, 32, 112, 117, 108, + 108, 95, 114, 101, 113, 117, 101, 115, 116, 58, 10, 10, 106, 111, + 98, 115, 58, 10, 32, 32, 116, 101, 115, 116, 58, 10, 32, 32, + 32, 32, 115, 116, 114, 97, 116, 101, 103, 121, 58, 10, 32, 32, + 32, 32, 32, 32, 102, 97, 105, 108, 45, 102, 97, 115, 116, 58, + 32, 102, 97, 108, 115, 101, 10, 32, 32, 32, 32, 32, 32, 35, + 32, 82, 101, 109, 111, 118, 101, 32, 116, 111, 32, 99, 97, 110, + 99, 101, 108, 32, 97, 108, 108, 32, 106, 111, 98, 115, 32, 117, + 112, 111, 110, 32, 116, 104, 101, 32, 102, 105, 114, 115, 116, 32, + 102, 97, 105, 108, 117, 114, 101, 10, 10, 32, 32, 32, 32, 32, + 32, 109, 97, 116, 114, 105, 120, 58, 10, 32, 32, 32, 32, 32, + 32, 32, 32, 114, 117, 110, 110, 101, 114, 58, 10, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 35, 32, 84, 104, 101, 115, 101, + 32, 97, 114, 101, 32, 116, 104, 101, 32, 109, 111, 115, 116, 32, + 114, 101, 99, 101, 110, 116, 32, 99, 111, 110, 102, 105, 103, 117, + 114, 97, 116, 105, 111, 110, 115, 32, 115, 117, 112, 112, 111, 114, + 116, 101, 100, 32, 98, 121, 32, 65, 108, 105, 114, 101, 46, 10, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 35, 32, 82, 101, + 109, 111, 118, 101, 32, 111, 114, 32, 97, 100, 100, 32, 114, 117, + 110, 110, 101, 114, 115, 32, 97, 115, 32, 110, 101, 101, 100, 101, + 100, 44, 32, 115, 101, 101, 32, 97, 118, 97, 105, 108, 97, 98, + 108, 101, 32, 114, 117, 110, 110, 101, 114, 115, 32, 97, 116, 10, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 35, 32, 104, 116, + 116, 112, 115, 58, 47, 47, 100, 111, 99, 115, 46, 103, 105, 116, + 104, 117, 98, 46, 99, 111, 109, 47, 101, 110, 47, 97, 99, 116, + 105, 111, 110, 115, 47, 104, 111, 119, 45, 116, 111, 115, 47, 117, + 115, 105, 110, 103, 45, 103, 105, 116, 104, 117, 98, 45, 104, 111, + 115, 116, 101, 100, 45, 114, 117, 110, 110, 101, 114, 115, 47, 117, + 115, 105, 110, 103, 45, 103, 105, 116, 104, 117, 98, 45, 104, 111, + 115, 116, 101, 100, 45, 114, 117, 110, 110, 101, 114, 115, 47, 97, + 98, 111, 117, 116, 45, 103, 105, 116, 104, 117, 98, 45, 104, 111, + 115, 116, 101, 100, 45, 114, 117, 110, 110, 101, 114, 115, 35, 115, + 116, 97, 110, 100, 97, 114, 100, 45, 103, 105, 116, 104, 117, 98, + 45, 104, 111, 115, 116, 101, 100, 45, 114, 117, 110, 110, 101, 114, + 115, 45, 102, 111, 114, 45, 112, 117, 98, 108, 105, 99, 45, 114, + 101, 112, 111, 115, 105, 116, 111, 114, 105, 101, 115, 10, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 45, 32, 117, 98, 117, 110, + 116, 117, 45, 108, 97, 116, 101, 115, 116, 32, 32, 32, 32, 32, + 35, 32, 76, 105, 110, 117, 120, 32, 120, 56, 54, 95, 54, 52, + 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 32, 117, + 98, 117, 110, 116, 117, 45, 50, 52, 46, 48, 52, 45, 97, 114, + 109, 32, 32, 35, 32, 76, 105, 110, 117, 120, 32, 65, 82, 77, + 54, 52, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, + 32, 109, 97, 99, 111, 115, 45, 49, 51, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 35, 32, 109, 97, 99, 79, 83, 32, 120, + 56, 54, 95, 54, 52, 10, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 45, 32, 109, 97, 99, 111, 115, 45, 108, 97, 116, 101, + 115, 116, 32, 32, 32, 32, 32, 32, 35, 32, 109, 97, 99, 79, + 83, 32, 65, 82, 77, 54, 52, 10, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 45, 32, 119, 105, 110, 100, 111, 119, 115, 45, + 108, 97, 116, 101, 115, 116, 32, 32, 32, 32, 35, 32, 87, 105, + 110, 100, 111, 119, 115, 32, 120, 56, 54, 95, 54, 52, 10, 10, + 32, 32, 32, 32, 114, 117, 110, 115, 45, 111, 110, 58, 32, 36, + 123, 123, 32, 109, 97, 116, 114, 105, 120, 46, 114, 117, 110, 110, + 101, 114, 32, 125, 125, 10, 32, 32, 32, 32, 115, 116, 101, 112, + 115, 58, 10, 32, 32, 32, 32, 32, 32, 45, 32, 117, 115, 101, + 115, 58, 32, 97, 99, 116, 105, 111, 110, 115, 47, 99, 104, 101, + 99, 107, 111, 117, 116, 64, 118, 52, 10, 10, 32, 32, 32, 32, + 32, 32, 45, 32, 110, 97, 109, 101, 58, 32, 83, 101, 116, 32, + 117, 112, 32, 65, 108, 105, 114, 101, 10, 32, 32, 32, 32, 32, + 32, 32, 32, 117, 115, 101, 115, 58, 32, 97, 108, 105, 114, 101, + 45, 112, 114, 111, 106, 101, 99, 116, 47, 115, 101, 116, 117, 112, + 45, 97, 108, 105, 114, 101, 64, 118, 53, 10, 10, 32, 32, 32, + 32, 32, 32, 45, 32, 110, 97, 109, 101, 58, 32, 66, 117, 105, + 108, 100, 32, 97, 110, 100, 32, 114, 117, 110, 32, 116, 101, 115, + 116, 115, 10, 32, 32, 32, 32, 32, 32, 32, 32, 114, 117, 110, + 58, 32, 97, 108, 114, 32, 116, 101, 115, 116, 10); + +end r.github_selftest_yml; diff --git a/src/templates/r.adb b/src/templates/r.adb index bef196d5..a13840a1 100644 --- a/src/templates/r.adb +++ b/src/templates/r.adb @@ -4,17 +4,20 @@ pragma Warnings (Off); pragma Style_Checks (Off); -with r.crate_test_tests_alire_toml; -with r.crate_test_tests_crate_test_tests_gpr; -with r.crate_test_tests_src_name_testsxassertions_enabled_adb; -with r.crate_test_tests_common_name_tests_ads; -with r.crate_common_gitignore_hidden; -with r.crate_bin_name_gpr; with r.crate_bin_alire_toml; +with r.crate_bin_name_gpr; with r.crate_bin_src_name_adb; -with r.crate_lib_name_gpr; +with r.crate_common_gitignore_hidden; with r.crate_lib_alire_toml; +with r.crate_lib_name_gpr; with r.crate_lib_src_name_ads; +with r.crate_test_tests_alire_toml; +with r.crate_test_tests_common_name_tests_ads; +with r.crate_test_tests_crate_test_tests_gpr; +with r.crate_test_tests_src_name_testsxassertions_enabled_adb; +with r.github_readme_md; +with r.github_publish_yml; +with r.github_selftest_yml; with Alire.Templates; with GNAT.Calendar; @@ -29,50 +32,62 @@ package body r is if not Initialized then Initialized := True; Register - ("crate_test/tests/alire.toml", - r.crate_test_tests_alire_toml.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); - Register - ("crate_test/tests/crate_test_tests.gpr", - r.crate_test_tests_crate_test_tests_gpr.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); - Register - ("crate_test/tests/src/name_tests-assertions_enabled." - & "adb", - r.crate_test_tests_src_name_testsxassertions_enabled_adb.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); - Register - ("crate_test/tests/common/name_tests.ads", - r.crate_test_tests_common_name_tests_ads.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); - Register - ("crate_common/gitignore.hidden", - r.crate_common_gitignore_hidden.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); + ("crate_bin/alire.toml", + r.crate_bin_alire_toml.Content'Access, + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); Register ("crate_bin/name.gpr", r.crate_bin_name_gpr.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); - Register - ("crate_bin/alire.toml", - r.crate_bin_alire_toml.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 56, 20, 0.0)); + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); Register ("crate_bin/src/name.adb", r.crate_bin_src_name_adb.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); Register - ("crate_lib/name.gpr", - r.crate_lib_name_gpr.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); + ("crate_common/gitignore.hidden", + r.crate_common_gitignore_hidden.Content'Access, + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); Register ("crate_lib/alire.toml", r.crate_lib_alire_toml.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 56, 20, 0.0)); + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); + Register + ("crate_lib/name.gpr", + r.crate_lib_name_gpr.Content'Access, + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); Register ("crate_lib/src/name.ads", r.crate_lib_src_name_ads.Content'Access, - GNAT.Calendar.Time_Of (2025, 03, 26, 17, 10, 47, 0.0)); + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); + Register + ("crate_test/tests/alire.toml", + r.crate_test_tests_alire_toml.Content'Access, + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); + Register + ("crate_test/tests/common/name_tests.ads", + r.crate_test_tests_common_name_tests_ads.Content'Access, + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); + Register + ("crate_test/tests/crate_test_tests.gpr", + r.crate_test_tests_crate_test_tests_gpr.Content'Access, + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); + Register + ("crate_test/tests/src/name_tests-assertions_enabled." + & "adb", + r.crate_test_tests_src_name_testsxassertions_enabled_adb.Content'Access, + GNAT.Calendar.Time_Of (2025, 04, 29, 05, 06, 37, 0.0)); + Register + ("github/README.md", + r.github_readme_md.Content'Access, + GNAT.Calendar.Time_Of (2025, 07, 10, 12, 00, 08, 0.0)); + Register + ("github/publish.yml", + r.github_publish_yml.Content'Access, + GNAT.Calendar.Time_Of (2025, 07, 10, 12, 00, 27, 0.0)); + Register + ("github/selftest.yml", + r.github_selftest_yml.Content'Access, + GNAT.Calendar.Time_Of (2025, 07, 10, 12, 06, 00, 0.0)); end if; end Init; diff --git a/support/embedder/templates.hash b/support/embedder/templates.hash index e1eda064..0eaf822b 100644 --- a/support/embedder/templates.hash +++ b/support/embedder/templates.hash @@ -1 +1 @@ -e4fc366ad747fdc58cf8fa18f5706a6851e2e67e1a511a3c8f45440e5407b5a8 +930317441edc8a903e2cbb92b3bc4733d31eeb81f7efe2bdde089112e8aa6c3c diff --git a/templates/github/README.md b/templates/github/README.md new file mode 100644 index 00000000..68abd3df --- /dev/null +++ b/templates/github/README.md @@ -0,0 +1,7 @@ + + +# @_UPPER:NAME_@ + +@_DESCRIPTION_@ \ No newline at end of file diff --git a/templates/github/publish.yml b/templates/github/publish.yml new file mode 100644 index 00000000..22aa4288 --- /dev/null +++ b/templates/github/publish.yml @@ -0,0 +1,28 @@ +name: Publish + +# REQUIRES a secret named ALR_PUBLISH_PAT to be set in the repository +# containing a token with write access to the repository (for tagging and +# releasing) and forking permissions (to create a fork of the community index +# and commit changes to it). + +# Running this workflow will open a PR against the community index for the +# version at the current commit. By default, it also will create a tag and +# release. Hence, it is recommended to only trigger it when one is certain all +# tests have succeeded for the version being submitted. + +on: + workflow_dispatch: # Enables manual triggering of the workflow + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: alire-project/alr-publish@v1 + with: + github_token: ${{ secrets.ALR_PUBLISH_PAT }} + skip_build: false + create_tag: true + create_release: true + # Check + # https://github.com/alire-project/alr-publish/blob/latest/action.yml + # for more options. diff --git a/templates/github/selftest.yml b/templates/github/selftest.yml new file mode 100644 index 00000000..a55125be --- /dev/null +++ b/templates/github/selftest.yml @@ -0,0 +1,34 @@ +name: Test + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + strategy: + fail-fast: false + # Remove to cancel all jobs upon the first failure + + matrix: + runner: + # These are the most recent configurations supported by Alire. + # Remove or add runners as needed, see available runners at + # https://docs.github.com/en/actions/how-tos/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories + - ubuntu-latest # Linux x86_64 + - ubuntu-24.04-arm # Linux ARM64 + - macos-13 # macOS x86_64 + - macos-latest # macOS ARM64 + - windows-latest # Windows x86_64 + + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v4 + + - name: Set up Alire + uses: alire-project/setup-alire@v5 + + - name: Build and run tests + run: alr test diff --git a/testsuite/drivers/alr.py b/testsuite/drivers/alr.py index d842abab..840cd6d4 100644 --- a/testsuite/drivers/alr.py +++ b/testsuite/drivers/alr.py @@ -663,16 +663,23 @@ def alr_settings_unset(key: str, local: bool = False): else: run_alr("settings", "--global", "--unset", key) -def alr_settings_set(key: str, value: str, local: bool = False): +def alr_settings_set(key: str, value: str, local: bool = False, builtin: bool = True): """ Set a key-value pair with `alr settings` Sets the value globally unless `local` is `True`. """ - if local: - run_alr("settings", "--set", key, value) - else: - run_alr("settings", "--global", "--set", key, value) + args=["settings"] + if builtin: + args.append("--builtin") + if not local: + args.append("--global") + args.append("--set") + args.append(key) + args.append(value) + + run_alr(*args) + def unselect_compiler(): """ diff --git a/testsuite/tests/get/custom-download-command/test.py b/testsuite/tests/get/custom-download-command/test.py index aadf50f7..5c127f60 100644 --- a/testsuite/tests/get/custom-download-command/test.py +++ b/testsuite/tests/get/custom-download-command/test.py @@ -8,7 +8,7 @@ import shutil from drivers.alr import crate_dirname, fixtures_path, run_alr, alr_settings_set from drivers.asserts import assert_match, assert_substring -from drivers.helpers import MockCommand +from drivers.helpers import MockCommand, on_windows # The script for the mock download command. Prints its arguments, then copies @@ -28,7 +28,8 @@ def set_download_cmd(cmd: str): # Mock `curl` so it always fails, and put the mock download command on `PATH`. -alr_settings_set("msys2.install_dir", os.path.abspath("does_not_exist")) +alr_settings_set("msys2.install_dir", os.path.abspath("does_not_exist"), + builtin=on_windows()) mock_curl = MockCommand("curl", "raise Exception", "cmd_dir") mock_download_cmd = MockCommand("command_name", COMMAND_SCRIPT, "cmd_dir") with mock_curl, mock_download_cmd: diff --git a/testsuite/tests/init/github-files/test.py b/testsuite/tests/init/github-files/test.py new file mode 100644 index 00000000..a00351c9 --- /dev/null +++ b/testsuite/tests/init/github-files/test.py @@ -0,0 +1,56 @@ +""" +Test --github switch functionality in alr init command +""" + +import shutil + +from drivers.alr import run_alr, alr_settings_set +from os.path import exists + +# Helper functions +def check_with_github_files(crate_path): + """Check that GitHub files were created in the specified crate directory""" + assert exists(f"{crate_path}/.github"), "GitHub directory not created" + assert exists(f"{crate_path}/.github/workflows"), "GitHub workflows directory not created" + assert exists(f"{crate_path}/.github/workflows/publish.yml"), "Publish workflow not created" + assert exists(f"{crate_path}/.github/workflows/selftest.yml"), "Self-test workflow not created" + assert exists(f"{crate_path}/README.md"), "README.md not created" + + +def check_no_github_files(crate_path): + """Check that GitHub files were not created in the specified crate directory""" + assert not exists(f"{crate_path}/.github"), "GitHub directory should not be created" + assert not exists(f"{crate_path}/README.md"), "README.md should not be created" + + +# Test --github=true generates GitHub files +run_alr("init", "--bin", "--github=true", "test_crate") +check_with_github_files("test_crate") + +# Test --github=false does not generate GitHub files +shutil.rmtree("test_crate") +run_alr("init", "--bin", "--github=false", "test_crate") +check_no_github_files("test_crate") + +# Test default behavior (no --github switch) +shutil.rmtree("test_crate") +run_alr("init", "--bin", "test_crate") +check_no_github_files("test_crate") +shutil.rmtree("test_crate") + +# Test --github switch without explicit value +run_alr("init", "--bin", "--github", "test_crate") +check_with_github_files("test_crate") +shutil.rmtree("test_crate") + +# Test implicit enabling via settings +alr_settings_set("init.github_files", "true") +run_alr("init", "--bin", "test_crate") +check_with_github_files("test_crate") +shutil.rmtree("test_crate") + +# Test explicit disabling via --github=false when enabled in settings +run_alr("init", "--bin", "--github=false", "test_crate") +check_no_github_files("test_crate") + +print('SUCCESS') diff --git a/testsuite/tests/init/github-files/test.yaml b/testsuite/tests/init/github-files/test.yaml new file mode 100644 index 00000000..a8cf9e3e --- /dev/null +++ b/testsuite/tests/init/github-files/test.yaml @@ -0,0 +1 @@ +driver: python-script \ No newline at end of file diff --git a/testsuite/tests/workflows/air-gapping/test.py b/testsuite/tests/workflows/air-gapping/test.py index 4bd98299..b97b75d6 100644 --- a/testsuite/tests/workflows/air-gapping/test.py +++ b/testsuite/tests/workflows/air-gapping/test.py @@ -29,10 +29,11 @@ for tool in TOOLS: mock_commands[tool].enable() # Changes to `PATH` are overridden in the case of MSYS2 tools, so we also # redirect `msys2.install_dir` to an empty directory. -msys2_dir = run_alr("settings", "--global", "msys2.install_dir").out.strip() -msys2_dir = msys2_dir.removeprefix("msys2.install_dir=") -empty_dir = os.path.join(os.getcwd(), "empty-dir") -alr_settings_set("msys2.install_dir", empty_dir) +if on_windows(): + msys2_dir = run_alr("settings", "--global", "msys2.install_dir").out.strip() + msys2_dir = msys2_dir.removeprefix("msys2.install_dir=") + empty_dir = os.path.join(os.getcwd(), "empty-dir") + alr_settings_set("msys2.install_dir", empty_dir) # Run `alr get hello`. This will fail because tar is unavailable. p = run_alr("get", "hello", quiet=False, complain_on_error=False) @@ -42,7 +43,7 @@ assert_match(".*Deployment of path .* to .* failed", p.out) # Disable tar mocking. If tar is provided by msys2, we need to make it available # explicitly because we have redirected `msys2.install_dir`. mock_commands["tar"].disable() -msys2_tar = os.path.join(msys2_dir, "usr", "bin", "tar.exe") +msys2_tar = os.path.join(msys2_dir, "usr", "bin", "tar.exe") if on_windows() else "" if on_windows() and os.path.isfile(msys2_tar): unmocked_tar = MockCommand( "tar", diff --git a/testsuite/tests_ada/src/alr_tests-commands_to_boolean.adb b/testsuite/tests_ada/src/alr_tests-commands_to_boolean.adb new file mode 100644 index 00000000..8da48557 --- /dev/null +++ b/testsuite/tests_ada/src/alr_tests-commands_to_boolean.adb @@ -0,0 +1,64 @@ + +with Alr.Commands.Testing; + +-- Check that the Alr.Commands.To_Boolean function does what we want in all +-- cases, which is: return Default if the switch is not set, return True if +-- given without a value, and return the Boolean'Value when a valid boolean +-- value is given. + +procedure Alr_Tests.Commands_To_Boolean is + + ----------- + -- Check -- + ----------- + + procedure Check (Value : String; Default, Expected : Boolean) is + Result : constant Boolean := Alr.Commands.Testing.To_Boolean (new String'(Value), "--dummy", Default); + begin + pragma Assert (Result = Expected, "Value=" & Value & " Default=" & Default'Image); + end Check; + + ----------------- + -- Check_Error -- + ----------------- + + procedure Check_Error (Value : String; Default : Boolean) is + begin + Check (Value, Default, False); + pragma Assert (False, "Should have raised an exception for value " & Value); + exception + when Alr.Commands.Wrong_Command_Arguments => + null; + end Check_Error; + +begin + -- Test cases where the default value should be returned + Check ("unset", True, True); + Check ("unset", False, False); + + -- Test cases where True should be returned + Check ("", True, True); + Check ("", False, True); + Check ("=", True, True); + Check ("=", False, True); + Check ("true", False, True); + Check ("True", False, True); + Check ("TRUE", False, True); + + -- Test cases where False should be returned + Check ("false", True, False); + Check ("False", True, False); + Check ("FALSE", True, False); + + -- Test cases with leading '=' + Check ("=true", False, True); + Check ("=false", True, False); + + -- Test cases that should raise an error + Check_Error ("invalid", True); + Check_Error ("1", False); + Check_Error ("0", True); + Check_Error ("yes", False); + Check_Error ("no", True); + +end Alr_Tests.Commands_To_Boolean; diff --git a/testsuite/tests_ada/src_common/alr-commands-testing.adb b/testsuite/tests_ada/src_common/alr-commands-testing.adb new file mode 100644 index 00000000..63fc1a30 --- /dev/null +++ b/testsuite/tests_ada/src_common/alr-commands-testing.adb @@ -0,0 +1,12 @@ +package body Alr.Commands.Testing is + + ---------------- + -- To_Boolean -- + ---------------- + + function To_Boolean (Image : GNAT.Strings.String_Access; + Switch : String; + Default : Boolean) + return Boolean renames Alr.Commands.To_Boolean; + +end Alr.Commands.Testing; \ No newline at end of file diff --git a/testsuite/tests_ada/src_common/alr-commands-testing.ads b/testsuite/tests_ada/src_common/alr-commands-testing.ads new file mode 100644 index 00000000..f6f6b142 --- /dev/null +++ b/testsuite/tests_ada/src_common/alr-commands-testing.ads @@ -0,0 +1,11 @@ +with GNAT.Strings; + +package Alr.Commands.Testing is + + function To_Boolean (Image : GNAT.Strings.String_Access; + Switch : String; + Default : Boolean) + return Boolean; + -- Public wrapper for the private Alr.Commands.To_Boolean function + +end Alr.Commands.Testing; \ No newline at end of file -- 2.39.5